From: "Jesús Gabriel y Galán" Date: 2013-02-07T00:55:49+09:00 Subject: Re: Implementing DRY with a function call On Wed, Feb 6, 2013 at 4:27 PM, Rob Marshall 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.