On Mon, Jan 16, 2012 at 10:03 PM, Sigurd <cu9ypd / gmail.com> wrote:
>
> On Jan 16, 2012, at 10:15 PM, Robert Klemme wrote:
>
>> Please do not top post.
>>
>> On Mon, Jan 16, 2012 at 7:08 PM, Sigurd <cu9ypd / gmail.com> wrote:
>>> it seems not quite accurate to me because of block. inject uses convent=
ion that the last statement in method is a return.

>>> =A0Therefore it's more natural to use short inject method definitions: =
either a.inject(5, :+) either 5 + a.inject(:+). =A0If the memo return in pr=
oc would be unnatural the inject won't pass it to the proc explicitly.
>>
>> ???
>
> The argue was about the explicit memo returns so on a given sample I trie=
d to show that that sample do not necessarily need to use blocks. But I see=
 no problem to explicitly return value if i was passed to that block. Yes, =
sometimes it looks ugly, sometimes, especially with tap, it looks pretty ni=
ce.

Funny thing is, that when you do x.inject(&:+) #inject actually sees a
block.  This is just a shorthand notation for doing x.inject {|a,b|
a+b}.  See doc of #to_proc and here:

irb(main):028:0> o =3D Object.new
=3D> #<Object:0x9f8966c>
irb(main):029:0> def o.to_proc; lambda {|*a| printf "block %p\n", a} end
=3D> nil
irb(main):030:0> def f;if block_given? then yield else puts "no block" end =
end
=3D> nil
irb(main):031:0> f() { puts 123 }
123
=3D> nil
irb(main):032:0> f
no block
=3D> nil
irb(main):033:0> f &o
block []
=3D> nil
irb(main):034:0> f(&o)
block []
=3D> nil

>>> On the other side I'm not a proponent of the crazy injects that could b=
e barely understood. I think in this case inject could be used easily as we=
ll as the other solutions provided.
>>>
>>> On Jan 16, 2012, at 6:14 PM, Adam Prescott wrote:
>>>
>>>> On Jan 16, 2012 4:09 PM, "Sigurd" <cu9ypd / gmail.com> wrote:
>>>>>
>>>>> You example is not accurate though:
>>>>>
>>>>> 5 + =A0[1, 2, 3, 4].reduce(&:+)
>>
>> Can you please again explain what is not accurate about Adam's piece
>> of code? =A0Are you aware of the two different behaviors of #inject?
>>
>
> Technically it's good. My argument was not that the code is not functiona=
l or doing something in a wrong way or that syntax is unacceptable. The poi=
nt i have is that Adams code is not the best example illustrating that the =
explicit inject block returns is the sign of incorrect inject use or let's =
call it "code smell". I'm not against that particular piece of code, it's j=
ust someone is wrong in internet again :)

Aha.  I would not have called that "not accurate".

>> irb(main):001:0> [[1,2,3],[1],[]].each do |a|
>> irb(main):002:1* p a, a.inject(&:+), a.inject(0, &:+)
>> irb(main):003:1> end
>> [1, 2, 3]
>> 6
>> 6
>> [1]
>> 1
>> 1
>> []
>> nil
>> 0
>> =3D> [[1, 2, 3], [1], []]
>>
>> Both have their use and it depends on the use case which you pick.
>
> I don't know can this be called different behavior. Inject use the first =
value of collection if it's not set explicitly so it's like particular case=
 of inject, but i'm ok with the two different cases as well.

It is different behavior because the block is invoked different number
of times.  And behavior is controlled by the fact whether an argument
is passed to #inject or not:

irb(main):016:0> [[1,2,3],[1],[]].each do |a|
irb(main):017:1* p a
irb(main):018:1> p a.inject {|x,y| printf "block 1: %p, %p\n", x, y;x+y},
irb(main):019:1* a.inject(0) {|x,y| printf "block 2: %p, %p\n", x, y;x+y},
irb(main):020:1* a.inject(nil) {|x,y| printf "block 3: %p, %p\n", x, y;x.to=
_i+y}
irb(main):021:1> end
[1, 2, 3]
block 1: 1, 2
block 1: 3, 3
block 2: 0, 1
block 2: 1, 2
block 2: 3, 3
block 3: nil, 1
block 3: 1, 2
block 3: 3, 3
6
6
6
[1]
block 2: 0, 1
block 3: nil, 1
1
1
1
[]
nil
0
nil
=3D> [[1, 2, 3], [1], []]

Cheers

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/