Около двух с половиной лет я работал в среде Python 2.x на своей старой работе. После смены компании Ruby и Rails заменили Python и Flask. На первый взгляд языки не кажутся особо разными, но определенно есть общие идиомы Ruby, которые мне нужно было выучить.

При добавлении новой функции я наткнулся на такой код:

if (variable = some_func()) 
  do_something(variable)
end

Интуитивно я догадался, что это означает «если some_func() что-то возвращает, do_something вместе с этим». Что заняло секунду, так это понимание того, что вы можете выполнять условные выражения присваивания.

Исходя из Python

В Python 2.x (и любом Python 3 до 3.8) присвоение переменной в условном выражении вернет синтаксическую ошибку:

>>> def some_func(): return 42;
...
>>> if (a = some_func())
  File "<stdin>", line 1
    if (a = some_func())
          ^
SyntaxError: invalid syntax

Скорее всего, присваивание в условном выражении — это опечатка, где программист хотел вместо этого сделать сравнение ==.

Этот тип опечатки является достаточно серьезной проблемой, поэтому существует стиль программирования под названием Условия Йоды, в котором постоянная часть сравнения помещается в левую часть оператора. Это вызвало бы синтаксическую ошибку, если бы вместо == использовалось =, например:

if (42 = x)
  ...

Назад к Руби

Теперь, когда я впервые столкнулся с такого рода присваиваниями в Ruby, я задумался, являются ли присваивания в условных выражениях хорошим стилем. Разумеется, в Руководстве по стилю Ruby есть раздел Безопасное назначение в условии . Раздел и примеры короткие и понятные. Вы должны взглянуть, если эта идиома Ruby нова для вас!

Что интересно в этой идиоме, так это то, что присваивание должно быть заключено в круглые скобки. Взгляните на примеры из Руководства по стилю Ruby:

# bad (+ a warning)
if v = array.grep(/foo/)
  do_something(v)
  # some code
end

# good (MRI would still complain, but RuboCop won't)
if (v = array.grep(/foo/))
  do_something(v)
  # some code
end

Почему первый пример плохой? Что ж, в Руководстве по стилю также сказано, что не следует заключать условные выражения в скобки. Скобки вокруг присваиваний в условных выражениях специально вызываются как исключение из этого правила.

Я предполагаю, что, применяя два разных соглашения, одно для чистых условных выражений, а другое для присваиваний в условных выражениях, теперь ответственность за решение того, что они хотят сделать, ложится на программиста. Это должно предотвратить опечатки, когда присваивание = используется вместо сравнения ==, или наоборот.

Эквивалент Python

Как упоминалось выше, присваивания в условных выражениях возможны в Python 3.8 через PEP 572. Вместо использования an= для таких назначений PEP ввел новый оператор :=. Поскольку круглые скобки более распространены в выражениях Python, введение нового оператора := (неофициально известного как оператор моржа!!), вероятно, было решением Python для проблемы с опечатками.

Первоначально опубликовано на https://julienchien.com.