[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

inject does not inject last value

Peña, Botp

8/7/2006 7:37:00 AM

Hi All,

inject is a powerful method in ruby. but the ff gives me surprise..

irb(main):001:0> sum=0
=> 0
irb(main):002:0> [1,2,3,4,5].inject{|sum,e| sum+e }
=> 15
irb(main):003:0> sum
=> 10
irb(main):004:0>
irb(main):006:0> RUBY_VERSION
=> "1.8.5"
irb(main):007:0> prod=1
=> 1
irb(main):008:0> [1,2,3,4,5].inject(1){|prod,e| prod*e }
=> 120
irb(main):009:0> prod
=> 24

it seems that inject does not update accumulator (sum or prod in examples) on last iteration.

tested on windows and linux.

kind regards

4 Answers

Gregor Kopp

8/7/2006 7:47:00 AM

0

irb(main):001:0> sum = [1,2,3,4,5].inject{|sum,e| sum+e}
=> 15
irb(main):002:0> sum
=> 15

Gregor Kopp

8/7/2006 7:50:00 AM

0

Gregor Kopp schrieb:
> irb(main):001:0> sum = [1,2,3,4,5].inject{|sum,e| sum+e}
> => 15
> irb(main):002:0> sum
> => 15

First you see the Return Value (15), but bevor assign the return value
to sum sum will be 10 and not the return value of the operation itself.
i cannot teach, im a dumpass english loser.

Ryan Davis

8/7/2006 8:50:00 AM

0


On Aug 7, 2006, at 12:36 AM, Peña, Botp wrote:

> Hi All,
>
> inject is a powerful method in ruby. but the ff gives me surprise..
>
> irb(main):001:0> sum=0
> => 0
> irb(main):002:0> [1,2,3,4,5].inject{|sum,e| sum+e }
> => 15
> irb(main):003:0> sum
> => 10

Inject is just an iterator:

% echo "sum=0; [1,2,3,4,5].inject{|sum,e| sum+e }" | parse_tree_show -f

[[:lasgn, :sum, [:lit, 0]],
[:iter,
[:call,
[:array, [:lit, 1], [:lit, 2], [:lit, 3], [:lit, 4], [:lit, 5]],
:inject],
[:masgn,
[:array,
[:lasgn, :sum], # <<<<<
[:dasgn_curr, :e]]],
[:call, [:lvar, :sum], :+, [:array, [:dvar, :e]]]]]

Because sum was assigned initially outside of the inject, it is an
lvar (local variable) instead of a dvar (dynamic/iter var, like e).
You'll notice that the assignments to both of those variables happens
before the call, and is part of the iteration mechanics itself. There
is no assignment done at the end of an iteration.

I think it is more important to point out that inject is
_just_another_iterator_. There is nothing special about it or how it
works. It is just a simple each just like everything else in
Enumerable. This makes the ruby implementation cleaner and easier to
maintain. Sum isn't an accumulator, as much as it is just another
variable. Should map or reject have some special semantics attached
to their block variables?

If you really are stuck on this idea, you can always change "sum+e"
to read "sum+=e" but at that stage, why use an inject at all?

Here is our implementation from metaruby:

def inject(memo = :_nothing)
enum = self.to_a.dup

memo = enum.shift if memo == :_nothing

return memo if enum.empty?

enum.each do |item|
memo = yield memo, item
end
return memo
end


Peña, Botp

8/7/2006 9:26:00 AM

0

fr Ryan:
[snipped cool samples]
# Because sum was assigned initially outside of the inject, it is an
# lvar (local variable) instead of a dvar (dynamic/iter var, like e).
# You'll notice that the assignments to both of those variables
# happens
# before the call, and is part of the iteration mechanics
# itself. There
# is no assignment done at the end of an iteration.
#
# I think it is more important to point out that inject is
# _just_another_iterator_. There is nothing special about it or how it
# works. It is just a simple each just like everything else in
# Enumerable. This makes the ruby implementation cleaner and easier to
# maintain. Sum isn't an accumulator, as much as it is just another
# variable. Should map or reject have some special semantics attached
# to their block variables?
#
# If you really are stuck on this idea, you can always change "sum+e"
# to read "sum+=e" but at that stage, why use an inject at all?
[snipped code explanation]

Hi Ryan, thank you for the very detailed and enlightening explanation. I apologize for being too dumb on this inject stuff (<banging head>).

kind regards -botp