Большинство из них знает о _
специальном значении «S в IRB в качестве держателя для последнего возвращаемого значения, но это не то , что я спрашиваю здесь.
Вместо этого я спрашиваю, _
когда используется в качестве имени переменной в старом старом коде Ruby. Здесь, похоже, он ведет себя по-особенному, сродни «переменной безразличия» (à la Prolog ). Вот несколько полезных примеров, иллюстрирующих его уникальное поведение:
lambda { |x, x| 42 } # SyntaxError: duplicated argument name
lambda { |_, _| 42 }.call(4, 2) # => 42
lambda { |_, _| 42 }.call(_, _) # NameError: undefined local variable or method `_'
lambda { |_| _ + 1 }.call(42) # => 43
lambda { |_, _| _ }.call(4, 2) # 1.8.7: => 2
# 1.9.3: => 4
_ = 42
_ * 100 # => 4200
_, _ = 4, 2; _ # => 2
Все они запускались непосредственно в Ruby (с puts
добавлением s), а не в IRB, чтобы избежать конфликта с его дополнительными функциями.
Это все результат моих собственных экспериментов, поскольку я нигде не могу найти никакой документации по такому поведению (по общему признанию, это не самая простая вещь для поиска). В конце концов, мне любопытно, как все это работает внутри, чтобы я мог лучше понять, в чем именно особенность _
. Поэтому я прошу ссылки на документацию и, желательно, на исходный код Ruby (и, возможно, RubySpec ), которые показывают, как _
ведет себя Ruby.
Примечание: большая часть этого возникла в результате обсуждения с @Niklas B.
lambda { |_, _| _ }.call(4, 2)
между 1.8 и 1.9 просто непреднамеренным побочным эффектом? Как и в «обычных» обстоятельствах, когда имя переменной не может быть продублировано, порядок, в котором они назначаются, не имеет значения.|_,_,...|
потому, что ошибка-дубликат была подавлена._
- действительный идентификатор. Идентификаторы не могут содержать только подчеркивания, они также могут быть подчеркиванием._ = o = Object.new _.object_id == o.object_id # => true
Вы также можете использовать его как имена методов:
def o._; :_ end o._ # => :_
Конечно, это не совсем читаемое имя, и при этом оно не передает читателю никакой информации о том, на что ссылается переменная или что делает метод.
IRB
, в частности, устанавливает_
значение последнего выражения:$ irb > 'asd' # => "asd" > _ # => "asd"
Как и в исходном коде , он просто устанавливает
_
последнее значение:@workspace.evaluate self, "_ = IRB.CurrentContext.last_value"
Изучал репозиторий. Вот что я нашел:
В последних строках файла
id.c
есть вызов:REGISTER_SYMID(idUScore, "_");
grep
Поиск источникаidUScore
дал мне два, казалось бы, релевантных результата:shadowing_lvar_gen
функцииwarn_unused_var
функцииshadowing_lvar_gen
кажется механизмом, посредством которого формальный параметр блока заменяет переменную с тем же именем, которая существует в другой области. Это функция, которая, кажется, вызываетSyntaxError
предупреждение «дублированное имя аргумента» и «затенение внешней локальной переменной».После
grep
добавления исходного кодаshadowing_lvar_gen
я обнаружил в журнале изменений для Ruby 1.9.3 следующее :Что, вероятно, является источником этой строки :
if (idUScore == name) return name;
Из этого я делаю вывод, что в такой ситуации, как
proc { |_, _| :x }.call :a, :b
одна_
переменная просто затеняет другую.Вот коммит, о котором идет речь . В основном он представил эти две строки:
if (!uscore) uscore = rb_intern("_"); if (uscore == name) return;
idUScore
Видимо, из тех времен, когда даже не существовало.источник
lambda { |_, _| 42 }
работы покаlambda { |x, x| 42 }
нет.|_, _|
работает, но|__, __|
не работает._
действительно имеет какое-то особое значение, я посмотрю, смогу ли я найти какую-нибудь информацию из исходного кода Ruby.