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.

I agree to what Jesus said: the block allows more control.  For
example you can also allocate resources and ensure they are cleaned up
properly after evaluating the block.

I am not 100% sure yet I understood your use case because I haven't
seen the identical pattern (as far as I can see you only posted one
example which makes it difficult for others to detect what your
multiple identical pieces of code have in common and what not).  Can
we maybe start over and see like 5 examples of these repeated calls?
Or get a more general explanation (i.e. in English and not code) what
repeated steps there are which are repeated.

> def return_value(val)
>  return "This is the returning value: #{val}"
> end

What do you need this for?

> 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?"

If you use the block form you can integrate the return_value logic
there and do not need to explicitly invoke that method.

> 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?

Yes, see Jesus example.

> 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

Sorry, but this is nonsense - it's the same as

ret = list[0]

and you are wasting a few CPU cycles.

Example:

irb(main):001:0> list = %w{foo bar}
=> ["foo", "bar"]
irb(main):002:0> lambda { list[0] }.call
=> "foo"

I get the impression that you didn't yet fully get the hang of blocks. :-)

>   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 do not even need to pass arguments to the /method/ to work with
them in the block:

def checked
  ret = yield
  raise "Foo" unless ret == 0
  ret
end

def foo(a, b)
  checked do
    a + b
  end
end

Kind regards

robert


-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/