I'm still making progress in learning ruby, but I ran across a problem
with lambda in loops wich gives me real headache until I found it. My
code looked like this:
a = []
for multi in [2, 3, 4, 5]
a << lambda do |n|
n * multi
end
end
for mul in a
puts mul.call(17)
end
I thought, this code will output four numbers 34, 51, 68, 85 but it
doesn't...
Instead it printed four times '85'. Obviously the four created blocks
are all using the same instance of 'multi'.
However, if I rewrite these lines to the following, it works as expected:
def create_mul multi
lambda do |n|
n * multi
end
end
b = []
for multi in [2, 3, 4, 5]
b << create_mul(multi)
end
for mul in b
puts mul.call(17)
end
So my question is: If there is an easy way to get the expected behavior
without a helper function like create_mul()?
In my app the lambdas to create in the loop are really small and I don't
would like to put their code outside the loop by reason of clarity.
I'm still making progress in learning ruby, but I ran across a problem
with lambda in loops wich gives me real headache until I found it. My
code looked like this:
a =
for multi in [2, 3, 4, 5]
a << lambda do |n|
n * multi
end
end
for mul in a
puts mul.call(17)
end
I thought, this code will output four numbers 34, 51, 68, 85 but it
doesn't...
Instead it printed four times '85'. Obviously the four created blocks
are all using the same instance of 'multi'.
However, if I rewrite these lines to the following, it works as expected:
def create_mul multi
lambda do |n|
n * multi
end
end
b =
for multi in [2, 3, 4, 5]
b << create_mul(multi)
end
for mul in b
puts mul.call(17)
end
So my question is: If there is an easy way to get the expected behavior
without a helper function like create_mul()?
--
email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna
> for multi in [2, 3, 4, 5]
> a << lambda do |n|
> n * multi
> end
> end
[2, 3, 4, 5].each do |multi|
a << lambda do |n|
n * multi
end
end
The each loop works because the variable multi is local to the
each block. Each iteration through that block will use a
different variable multi.
To me, it seems like a bug that the for loop isn't equivalent
to the each loop. I think it is putting multi in the
surrounding scope because of the syntactic order - multi comes
before the Enumerable.
You'll see the same problem if you assign multi before the each
loop. If you wanted to continue using the for loop (or multi
was already used), you could make a localized version of it
like this:
a =
for multi in [2, 3, 4, 5]
lambda do |multi_local|
a << lambda do |n|
n * multi_local
end
end.call(multi)
end
for mul in a
puts mul.call(17)
end
I didn't realize that within a block, the only variables truly
local are the argument variables. I think I've read somewhere
that in the future ruby will put better facilities in for
controlling variable scope locality.
···
--- ts <decoux@moulon.inra.fr> wrote:
> for mul in a
> puts mul.call(17)
> end
__________________________________
Yahoo! Mail - PC Magazine Editors' Choice 2005
It's an alternate form that has different scoping, similar to {} and do/end
which have different precedence.
I wouldn't consider it a bug. I would just consider it a very good reason
to never use a 'for' loop in a Ruby program.
···
On 9/28/05, Eric Mahurin <eric_mahurin@yahoo.com> wrote:
--- ts <decoux@moulon.inra.fr> wrote:
>
To me, it seems like a bug that the for loop isn't equivalent
to the each loop. I think it is putting multi in the
surrounding scope because of the syntactic order - multi comes
before the Enumerable.
--
Jim Freeze
WARNING: The Ruby populace has determined that using 'for'
loops in a Ruby script may be harmful to your health. You should
consult a pure Rubyist (who doesn't have ties to Perl or C) before
using this feature.