是否有一个ruby方法只返回一个块的值?

时间:2010-12-02 23:39:50

标签: ruby block

我知道Object#tap,它接受​​一个值并返回该值。但是有一个方法需要一个块并返回块所评估的值吗?

要改进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 个答案:

答案 0 :(得分:2)

您正在寻找的内容基本上等同于Lisp或OCaml中的let - 允许您临时将值绑定到标识符而不将新变量引入更大范围的内容。没有任何东西可以让你在Ruby中用这种语法做这样的事情。等价的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

答案 1 :(得分: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