Ruby 2.2.4, лексирующий назначение в условном выражении
В чем разница между этими двумя строками кода?
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)
1 ответ
Обе строки не будут работать. И обе линии будут работать. Это выражение Шредингера:).
Вы можете запустить его дважды в новом репле:
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"
Так что на самом деле Руби оценил 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
переменная не была определена в области действия оператора присваивания, когда она была оценена впервые. А на втором подходе это уже было определено, так что вы получили правильный результат.
Итак, никогда не делайте заданий таким образом