Переменная область действия, мешающая DSL в Ruby - PullRequest
0 голосов
/ 02 мая 2011
module Typecast
  class DSL
    def self.call(&blk)
      new.instance_eval(&blk)
    end
    def new_age(val)
      p val
    end
  end

  def typecast(&blk)
    DSL.call(&blk)
  end
  private :typecast
end

class Person
  include Typecast
  def age=(new_age)
    typecast do
      new_age :integer
    end
  end
end

Person.new.age = 10

# test.rb:33: syntax error, unexpected ':', expecting keyword_end
#       new_age :integer

Ruby возвращает эту ошибку, потому что знает, что new_age является локальной переменной, определенной в аргументах метода.Поэтому, когда я изменяю класс Person на этот:

class Person
  include Typecast
  def age=(new_val)
    typecast do
      new_age :integer
    end
  end
end

Ruby теперь возвращает ожидаемое :integer.

Мой вопрос заключается в том, как остановить локальные переменные, мешающие instance_eval блоков?

1 Ответ

0 голосов
/ 02 мая 2011

Когда у вас есть переменная и метод с одним и тем же именем, существующие в одной и той же области видимости, способ устранить неоднозначность - выяснить получателя.В этом случае вы хотите, чтобы получатель был self:

class Person
  include Typecast
  def age=(new_age)
    typecast do
      self.new_age :integer    # Avoids ambiguity because we used an
    end                        # explicit receiver.
  end
end

Person.new.age = 10
# => :integer
# => 10 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...