2010-12-02 128 views
0

我知道Object#tap,它接受一個值並返回該值。但有沒有一種方法需要一個塊並返回塊所評估的值?是否有一個ruby方法只返回一個塊的值?

爲了提高我在this answer代碼(這比下面的代碼片段更復雜的),我想改

deck.index("A").tap {|index| 
    STDERR.puts "Result of indexing for #{"A".inspect} is #{index.inspect}" 
} 

,已"A"反覆,到

def my_method(*args) 
    yield *args 
end 

deck = ['A', 'B', 'C'] 
my_method("A") {|value| deck.index(value).tap {|index| 
    STDERR.puts "Result of indexing for #{value.inspect} is #{index.inspect}" 
} } 
# Result of indexing for "A" is 0 
# => 0 

回答

2

你什麼在Lisp或OCaml中實質上相當於let--這使得您可以暫時將值綁定到標識符,而無需將新變量引入更大範圍。沒有什麼能讓你在Ruby中用這種語法來做這樣的事情。等效紅寶石是:

lambda {|value| deck.index(value).tap {|index| 
    STDERR.puts "Result of indexing for #{value.inspect} is #{index.inspect}" 
} }.call 'A' 

你當然可以只寫像一個方法:

def let(*values) 
    yield *values 
end 
+0

是否有可能把`'A'`附近開始,而不是接近尾聲? – 2010-12-03 00:18:58

0

我想你可以用光纖解決這個問題。喜歡的東西:

def myfiber 
    block = lambda{nil} 
    loop{ block = Fiber.yield(block.call) } 
end 
f = Fiber.new {myfiber } 
f.resume 

puts "result: #{f.resume(lambda{1})}" 
puts "result: #{f.resume(lambda{5})}" 
puts "result: #{f.resume(lambda{2})}" 

將導致:

result: 1 
result: 5 
result: 2 
相關問題