1

我想从yieldRuby 代码块中的 a 返回一个值。换句话说,我想将一个值从阻塞内部传递到块本身。

def bar
    puts "in block"
    foo = 1
    # The next line is wrong, 
    # but this is just to show that I want to assign a value to foo
    foo = yield(foo)
    puts "done block #{foo}"
end

puts "start"
bar do |shoop|
    puts "doing other stuff"
    shoop = 2
    puts "doing more stuff"
    # The following commented-out line would work, 
    # but I would rather not force the programmer 
    # to always put a variable at the end
    #shoop
end
puts "done"

我希望看到的输出是:

start
in block
doing other stuff
doing more stuff
done block 2
done

有什么方法可以在不依赖 Ruby 块末尾的隐式返回值的情况下实现这一点?Sinatra我相信这是可能的,因为我以前在代码块中看到过这种行为。

4

3 回答 3

3

您可以使用实例变量隐式返回值,就像在 Rails 中所做的那样:

def bar
  yield
  puts "The block has assigned @value to #{@value}"
end

bar do
  @value = 42
  nil # Do not return value intentionally
end

此代码输出:

The block has assigned @value to 42

更新

另一个不错的选择是使用辅助方法,许多框架也这样做:

def bar
  def render(value)
    @value = value
  end

  yield
  puts "The block has rendered #{@value}"
end

bar do
  render 42
  nil # Do not return value intentionally
end

此代码输出:

The block has rendered 42

更新 2

请参阅@Marek Lipka https://stackoverflow.com/a/19542149/203174的重要补充

于 2013-10-23T09:57:27.493 回答
1

可以滥用Object#tap

bar do |shoop|
  puts "doing other stuff"
  2.tap do
    puts "doing more stuff"
  end
end

点击 yield 到块,但结果是被点击的对象(在本例中为2)。

这是一个有趣的技巧,有时也很有帮助,但一个简单的临时变量通常更简单易读。

于 2014-03-01T18:02:05.730 回答
1

我必须警告您,@Daniel Vartanov 的答案仅适用self于方法和方法调用范围相同的情况。否则,应该在selfin 方法的上下文中调用该块,即:

def bar(&block)
  instance_eval(&block)
  puts "The block has assigned @value to #{@value}"
end
于 2013-10-23T12:47:54.853 回答