![](/img/trans.png)
[英]Writing an around_each filter in ruby for every method within a block.
[英]Calling a Ruby method recursively from within its associated block. Any other way?
我想出了這個:
def f x, &b
yield x, b
end
f 4 do |i, b|
p i
f i - 1, &b if i > 0
end
結果:
4
3
2
1
0
還有另一種方法嗎?
這取決於實際代碼的細節,但是在您的示例中,如果事先命名該塊,則可以避免在函數中產生該值和該塊。 例如:
def f(x, &b)
yield x
end
foo = lambda do |i|
p i
f(i-1,&foo) if i > 0
end
f(4,&foo)
但是,我想找到一個更優雅的解決方案。 我懷疑這將是Y組合器的良好應用。 只要您有更好的選擇,我就會更新此消息。
塊可以遞歸調用自身,只要它存儲在該塊本身可以訪問的變量中。 例如:
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
或者,您可以返回遞歸塊,將其綁定到調用者塊,然后調用該塊。 例如:
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)
輸出:
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
def f(x, &b)
b.call x
f(x-1,&b) if x>0
end
f(4) do |x|
p x
end
馬特的回答很好。 這也是從深度遞歸搜索中實現立即返回的唯一方法。 注意,從塊返回實際上是從調用函數返回。 一口氣消除所有遞歸塊調用。
有很多方法可以使用callcc或catch / throw(始終可以從深度遞歸調用中返回)來執行此操作。 這是使用線程本地變量的非高爾夫版本
def f x, &b
t = Thread.current
t[:b] ||= b
b ||= t[:b]
b.call(x)
ensure
t[:b] = nil
end
f 4 do |i|
p i
f i - 1 if i > 0
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.