2011-11-12 79 views
3

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

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

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

回答

2

有3种情况在这里这可能是相关的:

  • awesome2使用引用实例变量(本例中的块的定义者的实例变量
  • 定义者的实例变量这个块使用实例变量作为参数给接收者(没有机会把它作为块的参数)这是awesome的使用
  • 给出实例变量作为参数的块的用户的实例变量到块,这是的用法。

因此,让我们试着实现这两个例子来看看它们。的例子是冗长,相关线路有:

  • 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" 
+0

感谢您的解释。其他人可能也想阅读这个[简介](http://rubylearning.com/satishtalim/ruby_blocks.html)。我的问题不是这个,所以我问了一个新问题。 – m33lky

+0

另外,这是一个解决方案:'[1,2,3] .each {| bar | @ bar = bar}'取自[here](http://boga.wordpress.com/2008/04/15/ruby-19-porting-notes/)。 – m33lky

4

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

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

UPDATE 而不是使用实例变量,局部变量可以帮助您:

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

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

+0

我不能这样做。这就是我困惑的原因!看看我的[新问题](http://stackoverflow.com/questions/8107584/cant-access-activerecord-mutators-in-a-block)。 – m33lky

+0

好吧,明白了。我更新了我的帖子并回答了你的问题。 – WarHog