I've come up with this:
def f x, &b
yield x, b
end
f 4 do |i, b|
p i
f i - 1, &b if i > 0
end
Result:
4
3
2
1
0
Is there another way?
It depends upon the particulars of your actual code, but given your example, if you name the block beforehand, you can avoid yielding the value and the block in your function. Eg:
def f(x, &b)
yield x
end
foo = lambda do |i|
p i
f(i-1,&foo) if i > 0
end
f(4,&foo)
However, I'd like to find a more elegant solution to this problem. I suspect this is would be a good application of the Y combinator. As soon as I have something better for you, I'll update this message.
A block can recursively call itself provided it is stored in a variable that is accessible by the block itself. For example:
def f(x)
block = lambda do |y|
# some calculation on value, or simply yield to the block passed to f()
yield y
block.call(y - 1) if y > 0
end
block.call(x)
end
f(4) do |x|
puts "Yielded block: #{x}"
end
Alternatively, you can return the recursive block, bound to the callers block and then call that block. For example:
def g
block = lambda do |y|
# some calculation on value, or simply yield to block passed to g()
yield y
block.call(y - 1) if y > 0
end
end
printing_descender = g do |x|
puts "Encapsulated block: #{x}"
end
printing_descender.call(4)
Outputs:
Yielded block: 4
Yielded block: 3
Yielded block: 2
Yielded block: 1
Yielded block: 0
Encapsulated block: 4
Encapsulated block: 3
Encapsulated block: 2
Encapsulated block: 1
Encapsulated block: 0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With