Ruby 2.2.4 lexing присвоение в условном

112
13

В чем разница между этими двумя строками кода?

a = (b if (b = "test"))
a = b if (b = "test")

Первый работает отлично и задает как a и b для test, но второй вызывает ошибку:

NameError: неопределенная локальная переменная или метод 'b' для main: Object

Я бы предположил, что для второй строки Ruby сначала оценил b = "test", затем if "test" и, наконец, a = b. Что на самом деле происходит?

(Версия Ruby версии 2.2.4)

спросил(а) 2021-01-12T19:43:52+03:00 1 неделя, 3 дня назад
1
Решение
74

Обе линии не будут работать. И обе линии будут работать. Это выражение schrödinger :).

Вы можете запустить его дважды в новом реплике:

a =  b if b = "test"
#=> NameError: undefined local variable or method 'b' for main:Object
a = b if b = "test"
#=> "test"

Давайте посмотрим глубже, откройте новую реплику:

defined(b)
#=> nil
a = b if b = "test"
#=> NameError: undefined local variable or method 'b' for main:Object
defined(b)
#=> local-variable
b
#=> "test"
a = b if b = "test"
#=> "test"

Таким образом, на самом деле Ruby оценил часть b = "test" и определил эту переменную в текущей области. Оба выражения a = b и if b = "test" выполнялись. Более того, если оператор выполнения выполняется перед оператором присваивания:

c = p("assignment") && b if b = p("if") && "test"
#=> "if"
#=> "assignment"
#=> NameError: undefined local variable or method 'b' for main:Object

Но переменная b не была определена в области применения присваивания, когда она была впервые оценена. А на втором подходе он уже был определен, поэтому вы получили правильный результат.

Итак, никогда не выполняйте задания таким образом

ответил(а) 2021-01-12T19:43:52+03:00 1 неделя, 3 дня назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема