块中的实例变量

时间:2011-11-12 08:16:30

标签: ruby

如何将实例变量作为参数传递给块?

这在Ruby 1.9中不起作用(形式参数不能是实例变量)。

awesome do |foo, @bar|
  puts 'yay'
end

2 个答案:

答案 0 :(得分:4)

Ruby 1.9使块参数成为块本地。这也意味着块参数不再是全局变量或实例变量。您可以将闭包用于您的目的:

@foo = 10
1.times do |i|
  puts @foo
end
# => "10"

<强>更新 本地变量可以帮助您:

,而不是使用实例变量
foo = 10
1.times do |i|
  puts foo
end
# => "10"

在这种情况下,您不会遇到与不同上下文中的代码执行相关的问题。

答案 1 :(得分:2)

这里有3个案例可能是相关的:

  • 引用实例变量的块定义器的实例变量(在示例中为awesome2的用法。
  • 块定义器的实例变量,它将实例变量作为参数提供给接收者(没有机会将其作为参数提供给块)。这是awesome
  • 的用法
  • 块用户的实例变量,它将实例变量作为块的参数。这是awesome3
  • 的用法

因此,让我们尝试实现这两个示例来查看它们。这个例子很冗长,相关的行是:

  • awesome获取实例变量作为参数,然后接收器在块的调用中使用
  • awesome2没有实例变量,它由Sender#use_in_block绑定。接收者没有机会改变这种约束力。
  • awesome3获取发件人的实例变量,但使用自己的实例变量来调用块

因此,根据您想要达到的目标,三者中的一个是更好的解决方案。

class Sender
  attr_accessor :send_var
  def call_a_block(var)
    rec = Receiver.new(5)
    @my_var = var
    res = rec.awesome(@my_var) do |arg1|
      arg1 + 3
    end 
    res2 = rec.awesome3(@my_var) do |arg1|
      arg1 + 3
    end
    p "Result of calling awesome with: 3 and #{@my_var} is #{res}"
    p "Result of calling awesome3 with: 3 and #{@my_var} is #{res2}"
  end
  def use_in_block(var)
    rec = Receiver.new(6)
    @my_var = var
    res = rec.awesome2 do
      4 + @my_var
    end
    p "Result of calling awesome2 with: 4 and #{@my_var} is #{res}"
  end
end

class Receiver
  attr_accessor :rec_var
  def initialize(var)
    @rec_var = var
  end
  def awesome(arg1)
    res = yield(arg1)
    res * 2
  end
  def awesome3(arg1)
    res = yield(@rec_var)
    res * 2
  end
  def awesome2
    res = yield
    res * 2
  end
end

s = Sender.new
s.call_a_block(7)
s.call_a_block(20)
s.use_in_block(7)
s.use_in_block(20)

结果是:

c:\Temp>ruby call.rb

"Result of calling awesome with: 3 and 7 is 20"
"Result of calling awesome3 with: 3 and 7 is 16"
"Result of calling awesome with: 3 and 20 is 46"
"Result of calling awesome3 with: 3 and 20 is 16"
"Result of calling awesome2 with: 4 and 7 is 22"
"Result of calling awesome2 with: 4 and 20 is 48"