Создание метода установки, который принимает дополнительные аргументы в Ruby

Я пытаюсь написать метод, который действует как установщик и принимает дополнительные аргументы помимо назначенного значения. Глупый пример:

class WordGenerator
  def []=(letter, position, allowed)
    puts "#{letter}#{allowed ? ' now' : ' no longer'} allowed at #{position}"
  end

  def allow=(letter, position, allowed)
    # ...
  end
end

Написание его как индексатора работает, и я могу назвать его так:

gen = WordGenerator.new

gen['a', 1] = true
# or explicitly:
gen.[]=('a', 1, true)

Но когда я пытаюсь выполнить любое из следующих действий, интерпретатор жалуется:

gen.allow('a', 1) = false # syntax error
gen.allow=('a', 1, false) # syntax error

Почему это не сработает, я упускаю очевидное?


person Valentin Milea    schedule 04.03.2010    source источник
comment
связанные/дубликаты: stackoverflow.com/questions/ 9280623/   -  person kotique    schedule 15.06.2012


Ответы (2)


Это не работает, потому что синтаксический анализатор не позволяет этого. Знак равенства разрешен в выражениях формы identifier = expression, expression.identifier = expression (где идентификатор равен \w+), expression[arguments] = expression и expression.[]= arguments, а также как часть строки, символа или символьного литерала (?=). Вот и все.

gen.send(:allow=, 'a', 1, false) будет работать, но в этот момент вы можете просто дать методу имя, которое не включает =.

person sepp2k    schedule 04.03.2010
comment
Спасибо. Забавно, что он позволяет такие вещи, как 'def seed=(value) end; gen.seed=(1)'. Я ожидал, что 'seed=' будет идентификатором, но (если я правильно понял ваши правила) он выглядит так: [gen/expr].[seed/identifier]=[(1)/expr]. Это объясняет, почему он терпит неудачу с более чем одним аргументом - (a) является выражением, а (a, b) - нет! Предполагая, что это так, как работает 'gen.[]=('a', 1, true)'? - person Valentin Milea; 04.03.2010
comment
.[]= — это еще один частный случай, который я забыл в своем списке выше (наряду с expression[comma_seperated_expressions] = expression, который, конечно, тоже работает). - person sepp2k; 04.03.2010

Я столкнулся с этим и решил передать свои аргументы в виде массива или хэша.

E.g.:

def allow=(arguments)
  puts arguments[:letter]
  puts arguments[:position]
  puts arguments[:allowed]
end

object.allow={:letter=>'A',:position=>3,:allowed=>true}
person Ross F    schedule 17.12.2011