From: gwtmp01@... Date: 2007-02-06T02:15:48+09:00 Subject: Re: Proc vs lambda vs proc This thread caused me to do some experimenting and I came across some Proc semantics that I hadn't seen discussed before and that might be useful in a DSL context. Consider: class A Foo = define_method(:foo) { |x| p "self: #{self}" return 'positive' if x > 0 'negative' } end p A::Foo # # p A::Foo.call(0) # "self: A" "negative" p A::Foo.call(1) # "self: A" "positive" p A.new.foo(0) # "self: #" "negative" p A.new.foo(1) # "self: #" "positive" I was unaware that define_method returned a proc. I was even more surprised that it appears to be of the lambda "flavor". That is to say that a 'return' within the block is relative to the block and not to the scope where the block is defined. Previously I thought that only Kernel#proc and Kernel#lambda had the 'magic' property of altering the return semantics of a block. I understand why this is also necessary for define_method to be useful, I was just not aware that the resulting proc was accessible as the return value of define_method. I was going to ask if there was any way to write a method like 'define_method' that forces any provided blocks to be interpreted as lambda vs. 'regular' procs. Then I did some more experimenting: a = Proc.new { return 42 } a.call # LocalJumpError b = lambda &a a.call # 42 This was another surprise for me as I figured that when lambda was used, the first proc would be 'wrapped' in a new proc with lambda semantics, something like: c = lambda { a.call } But that isn't the case. If you try 'c.call' you'll get the LocalJumpError again. I hadn't see this type of transformation before. It might be useful in some DSL situations: class A filter {|x| x.to_s } # ok filter {|x| return x.to_s } # potential LocalJumpError end If you wrote filter as: def A.filter(&b) lambda(&b).call(42) end you can avoid the LocalJumpError. Gary Wright