"Bob Sidebotham" <bob@windsong.bc.ca> 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:0x100d43f0 @create=#<Proc:0x100d4450@(irb):41>>
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