On Wed, Feb 6, 2013 at 4:27 PM, Rob Marshall <lists / ruby-forum.com> wrote:
> Hi Jesus,
>
> Thanks for the help. I think I see your point about the "lambda {}call"
> simply returning the already evaluated expression, as opposed to
> actually evaluating it at the time of the yield. But in my case it
> doesn't really matter.
> Where the expression gets evaluated is less
> important than making sure I check for errors immediately afterward.

Unless the expression raises an exception. Passing the result of the
call means that the call is perform at a point where no exception
handling is being done, while if you pass a block, you can execute it
in a controlled place, where you can catch excepctions and handle
them.

> So,
> from my perspective (and in this case) I am getting the "correct"
> result. Here's what I've tried in irb (removing the prompt):
>
> def use_yield
>   ret = yield
>   puts "This is where I check for errors"
>   return ret
> end
>
> def use_lambda(func)
>   ret = lambda {func}.call
>   puts "This is where I check for errors"
>   return ret
> end
>
> def return_value(val)
>  return "This is the returning value: #{val}"
> end
>
> use_yield { return_value("who cares?") }
> This is where I check for errors
> => "This is the returning value: who cares?"
>
> use_lambda(return_value("who cares?"))
> This is where I check for errors
> => "This is the returning value: who cares?"
>
> Again, they both seem to be doing the exact same thing. And in my module
> it is working correctly, giving me the results I want.
>
> Plus I would like to add a slight wrinkle, i.e. the ability to pass in
> additional arguments. The yield method doesn't seem to allow me to pass
> in anything but a block and I don't seem able to set local variables,
> etc. With the "lambda {}.call" I can pass a variable argument list and
> do additional testing on the items in the list as well as execute the
> function (the last item on the argument list). Or is there some way to
> pass/initialize additional arguments in a block that will get evaluated
> by the yield?
>
> For example:
>
> def use_lambda(*list)
>   if list.length > 1
>     list[0..-2].each_with_index {|v,i| puts "This is argument #{i}:
> #{v}"}
>     list.slice!(0..-2)
>   end
>   ret = lambda { list[0] }.call
>   puts "This is where I test for errors"
>   return ret
> end
>
> Doing that I can pass as many additional arguments as I want and
> evaluate them etc. I haven't figured out how to do that with the
> block/yield method.

You can pass a variable argument list to a block too:

1.9.2p290 :001 > def yield_args *args
1.9.2p290 :002?>   yield *args
1.9.2p290 :003?>   end
 => nil
1.9.2p290 :004 > yield_args(1,2,3,4) {|a,b,c,d| p a,b,c,d}
1
2
3
4
 => [1, 2, 3, 4]
1.9.2p290 :005 > yield_args(1,2,3,4) {|*args| p args}
[1, 2, 3, 4]
 => [1, 2, 3, 4]

Jesus.