From: Dan Doel Date: 2003-08-27T16:45:59+09:00 Subject: Blocks, eval and named parameters Hello, So I was reading the brief discussion on named parameters in the gigantic troll-fueled thread (forward note, the hash option wasn't discussed, and I do know about it, so I don't need to be lectured :) ), and I saw the example of named parameters in a constructor like so: class Foo attr_accessor :foo, :bar def initialize ... yield self if block_given? end end Foo.new { |obj| obj.foo = 5; obj.bar = 6 } And someone liked it. However, this isn't really any better than: obj = Foo.new obj.foo = 5 obj.foo = 6 Unless you make the accessors private, in which case I think you need to instance_eval the block. So, I got to thinking of a way to possibly use a block to assign to local variables. For example, thinking of the up-and-coming scoping rule changes, maybe one could do: class Foo def initialize(&blk) if blk instance_eval &blk end @height = height end end Foo.new do height = 5 end However, then I thought, perhaps this already works like so: class Foo def initialize(height=nil, &blk) if blk then instance_eval &blk end @height = height end end Since height will be defined as a local variable, and should propogate out. However, instance_eval doesn't work this way, so I doubt that it will work with the new scoping rules. So, finally for my question: instance_eval, class_eval and module_eval all optionally take code blocks to evaluate in a certain context. However, eval itself only takes a string. Is there, or will there ever be a way to evaluate a code block with an arbitrary binding object/in an arbitrary context, so that something like the above will work? I suppose a block used in such a way is no longer a closure, but it could be an interesting addition to Proc's (note, I'm not sure how much utility it would have outside this example). Until then, I think the closest I can come to named parameters using blocks is: class Foo def initialize(&blk) if blk bnd = blk.call @height = eval "height", bnd end end end Foo.new do height = 6; binding end Then again, writing to allow: Foo.new(:height => 6) Isn't terribly hard, looks fine, and allows you to still pass a block for other purposes if you need it, so I don't think things should be changed merely for this example's sake. Anyhow, any thoughts on all this? Thanks in advance for the stuff I'll probably learn from any discussion that ensues. - Dan