Eric Mahurin wrote:
> --- "Berger, Daniel" <Daniel.Berger / qwest.com> wrote:
...
>>class Foo
>>   attr_accessor :bar, :baz, :zap
>>   def initialize
>>      yield self if block_given?
>>   end
>>end
>>
>>foo = Foo.new do |f|
>>   f.bar = "hello"
>>   f.baz = 5
>>   f.zap = "world"
>>end
> 
> 
> What's the advantage of this over:
> 
> foo = Foo.new
> foo.bar = "hello"
> foo.baz = 5
> foo.zap = "world"

One advantage is you can construct and configure an object without
assigning to a local variable. This can be useful if you are
constructing a bunch of objects in #map or in literal hashes or arrays
or (this is a bit far-fetched, but why not) parameter lists. And it is
nice not to add a symbol to the namespace. I particularly like the fact
that if you are doing several of these, possibly even in different
methods, you can use the same |f| parameter and cut and paste between
the assignments:

def make_foos
  foo1 = Foo.new do |f|
    f.bar = "BAR"
  end

  foo2 = Foo.new do |f|
    f.bar = "ZAP"
  end
end

That has a nice standardized look to me, especially when you are
populating many fields in several different methods.

> Is it method chaining?  You want this thing to return foo?  You
> could just end this statement list with "foo", or you could use
> "ensure":
> 
> begin
>   foo = Foo.new
> ensure
>   foo.bar = "hello"
>   foo.baz = 5
>   foo.zap = "world"
> end

Danger Will Robinson. An exception may happen in Foo.new....

> This begin..ensure..end expression returns foo (the result
> before ensure) not "world" as you might expect.  Great for
> doing post operations after you calculate a return value
> (equivalent of C's i++ is another example).

You can use an else clause to return a value from a begin..end block,
but only if there is at least one rescue clause (or else you get a warning).

p(
begin
  a = []
  a << 1
  a << 2
rescue
else
  a
end
)

# ==> [1, 2]

-- 
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407