Подтвердить что ты не робот

Какова логика этого результата?

def foo(_, _='override')
  _
end

p foo("bye bye")
p foo("hello", "world")

Вывод:

"override"
"hello"

Я мог понять, был ли результат:

"override"
"world"

или даже:

"bye bye"
"hello"

Но результат, который я получаю, вызывает у меня путаницу.

4b9b3361

Ответ 1

Аргументы по умолчанию оцениваются раньше времени, чем обычные аргументы, если для него передан аргумент, иначе они оцениваются последним. Почти уверен, но не уверен, как это доказать.

Значение в этом примере:

во время 0 вызов p foo("hello", "world")

в момент времени 1 _ = 'override'

во время 2 _ = "world"

в момент времени 3 _ = "hello"

в 4 раза печатаются переменные, и вы видите "привет"

EDIT вот некоторые доказательства:

def foo(_, _='override',_)
  _
end

p foo("bye bye","goodbye")
p foo("hello", "world", "three")

печатает

"override"
"three"

Ответ 2

Я не могу найти лучшего объяснения, чем этот

подчеркивание рубиновой магии

Причиной этого является парсер Rubys в shadowing_lvar_gen. Все нормальные проверки дублирования пропускаются, если имя переменной состоит из ровно одного подчеркивания.

Ответ 3

Одним из возможных объяснений является то, что имя _ означает "неиспользуемая переменная". Вы не должны даже ссылаться на него, не говоря уже о том, чтобы ожидать каких-либо значений. Поскольку это особое имя, он получает специальное лечение от анализатора (например, подавление ошибок "дублирующего параметра" ). Я полагаю, что никто не заботился о том, чтобы этот код вызывал логический результат, потому что опять же это неиспользуемые переменные.

Если вы переименуете его на что-нибудь еще (скажем, a), вы получите сообщение об ошибке, потому что теперь эта подпись метода не имеет смысла.