On Wed, 28 Sep 2005, Michael Roth wrote:

> Hello all,
>
> 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()?

you don't have to write a __specific__ helper method - you can have a general
purpose one to help with cases like these:

   harp:~ > cat a.rb
   def scope *a; yield *a; end

   a = []

   for multi in [2, 3, 4, 5]
     a << scope(multi){|m| lambda{|n| n * m} }
   end

   for mul in a
     puts mul.call(17)
   end


   harp:~ > ruby a.rb
   34
   51
   68
   85

or go golfing

   harp:~ > cat a.rb
   puts (2 .. 5).map{|m| lambda{|n| n * m} }.map{|l| l.call 17}

   harp:~ > ruby a.rb
   34
   51
   68
   85

cheers.

-a
-- 
===============================================================================
| 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
===============================================================================