2010-12-02 176 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 
相关问题