2011-11-12 3 views
3

Как передать переменную экземпляра в качестве аргумента в блок?переменная экземпляра в блоках

Это не работает в Ruby 1.9 (формальный аргумент не может быть переменной экземпляра).

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

ответ

2

Есть 3 случая здесь, которые могут иметь отношение:.

  • Instance переменной Определитель блок, который ссылается на переменном экземпляр (в данном примере использования awesome2
  • Instance переменной Определитель блока, который дает переменную экземпляра в качестве аргумента приемнику (нет возможности дать его как аргумент блоку). Это использование 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" 
+0

Спасибо за объяснение. Другие могут захотеть прочитать это [intro] (http://rubylearning.com/satishtalim/ruby_blocks.html). Моя проблема была не в этом, поэтому я задал новый вопрос. – m33lky

+0

Кроме того, это решение: '[1,2,3] .each {| bar | @ bar = bar} 'взято из [здесь] (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

Смежные вопросы