簡體   English   中英

從關聯的塊中遞歸調用Ruby方法。 還有其他方法嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM