From: Robert Klemme Date: 2004-09-24T04:59:34+09:00 Subject: Re: "no block given" with closure? "Bob Sidebotham" schrieb im Newsbeitrag news:rrD4d.483473$M95.426973@pd7tw1no... > When I execute this code, I get "no block given (LocalJumpError)": > > class S > def initialize(&b1) > @b1 = b1 > end > def each > @b1.call > end > end > > s = S.new {[1,2,3].each {|i| yield i }}.each {|v| puts v} > > Changing the implied block/yield combination to an explicit proc object > works, as follows: > > class S > def initialize(&b1) > @b1 = b1 > end > def each(&b2) > @b1.call(b2) > end > end > > s = S.new { |p| [1,2,3].each { |i| p.call(i) }}.each {|v| puts v} > > This prints the expected 3 lines. > > This is with ruby 1.8.2 (2004-09-10) [i686-linux] > > It's quite possible that I don't understand how this is supposed to work > :-). Any hints would be appreciated. Possibly. The yield in the first example has no block that it can invoke, much the same as when you invoke "yield" directly: >> yield LocalJumpError: no block given from (irb):1 You make it a bit too complicated, IMHO. If you just want to invoke some block on an Enumerable, then you can have that directly (the yield block in the first example basically just forwards the element). So you could do this as well: class S def initialize(enum) @enum = enum end def each(&b) @enum.each &b end end s = S.new([1,2,3]).each {|v| puts v} OTOH, if you want to use the block to generate a value which is used for the enumeration you could do class S def initialize(&create) @create = create end def each(&b) @create.call.each &b end end s = S.new { [1,2,3] }.each {|v| puts v} The subtle difference between these two is, that the second approach creates something on each invocation of S#each and iterates over it while in the first case all iterations run through the same instance: >> s = S.new { [rand(10), rand(10)] } => #> >> s.each {|v| puts v} 1 6 => [1, 6] >> s.each {|v| puts v} 0 6 => [0, 6] >> ?> s.each {|v| puts v} 0 5 => [0, 5] >> Hope this makes things a bit clearer. Kind regards robert