2009-11-23 29 views

回答

4

這取決於你的實際代碼的細節,但是舉個例子,如果你事先給塊命名,你可以避免產生函數中的值和塊。例如:

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組合器的一個很好的應用。只要我有更好的東西給你,我會更新這條消息。

+0

這很好,雖然我對我的案例的lambda表示懷疑,因爲它與def f..end的字節數大致相同。這變得有點抽象,但一切都從這個開始:http://stackoverflow.com/questions/1766675/code-golf-running-water/1770264#1770264 – DigitalRoss 2009-11-24 02:51:47

+0

是的,不幸的是,如果它是最少數量的字符使用你之後,使用lambda可能不會很有幫助。即使在Ruby 1.9中找到的縮寫 - >語法仍然可能不會節省太多,一旦包含y組合代碼。如果您不熟悉它,或者有其他讀者,可以在這裏找到Ruby中的示例:http://nex-3.com/posts/43-fun-with-the-y-combinator-in-ruby和這裏:http://www.eecs.harvard.edu/~cduan/technical/ruby/ycombinator.shtml – 2009-11-24 04:05:32

+0

仍然是一個非常有趣的問題。在接受命名的lambda是最短的路線之前,我會更多地咀嚼它。 – 2009-11-24 04:06:48

1
def f(x, &b) 
    b.call x 
    f(x-1,&b) if x>0 
end 

f(4) do |x| 
p x 
end 
2

塊可以遞歸調用自己,只要它存儲在塊本身可訪問的變量中。例如:

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 
0

馬特的回答是好。它也是實現從深度遞歸搜索立即返回的唯一方法。請注意,從塊中返回實際上是從調用函數返回的。一舉解除所有遞歸塊調用。

+0

這實際上取決於你是否使用'lambda'或'proc'。 lambda是可以返回的匿名函數,proc在父函數的範圍內執行,並且返回將按照您的說法執行。 – 2014-03-04 02:39:38

0

有很多方法可以使用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