SCoon

and или && ?

Оценить эту запись
К непереведенному пока фрагменту из "Scripting in RGSS Ruby for Intermediate and Experts": при чтении разделов 7.3 и 7.4 нужно учитывать, что обнаруженные Blizzard'ом "ошибки" в действительности объясняются недостаточным знанием Ruby.

Многих при изучении Ruby подводит сходство &&/|| и and/or -- особенно тех, кто раньше писал на языках Виртовского семейства (Pascal, Delphi, Modula-2 и т.п.). При беглом знакомстве кажется, что && -- это то же, что и and, а || -- то же, что и or. К сожалению, это не так.

Формальное различие между ними состоит в приоритетах: && приоритетнее ||, тогда как приоритеты and и or равны. Более того, and и or имеют очень низкий приоритет. Поэтому попытка просто использовать and вместо && приводит, к примеру, к таким казусам:

Код:
foo = true
bar = false
buzz = foo and bar
puts buzz
...и получаем на экране "true". Ошибка? Нет. Просто выражение "buzz = foo and bar" означает вовсе не "buzz = (foo and bar)", а "(buzz = foo) and bar". Как я уже говорил, приоритет у and и or ОЧЕНЬ низкий.

Странное и необычное поведение для булевых операторов? Верно. Это потому, что and и or вовсе не булевы операторы, а операторы управления порядком исполнения, родные братья if и unless.

Сюрприз, не правда ли?

Соответственно, Blizzard прав -- использовать and и or внутри if, как правило, не стоит. А где же их использовать?

Предположим, у нас есть несколько функций, каждая из которых возвращает либо нужное нам значение, либо nil (false) при аномальной ситуации. И мы хотим последовательно вызвать эти функции, причем при успехе результат одной функции иногда будем передавать на вход следующей. Пример:

Код:
if x = foo(1) 
  if y = bar(x) 
    z = buzz(x, y)
  end
end
Несколько рыхловато, не правда ли? Вот как раз для такой распространенной ситуации и придуман оператор and. Во что он превратит этот код:

Код:
x = foo(1) and y = bar(x) and z = buzz(x, y)
Одна строка прекрасно читаемого кода. А что, если мы хотим явно задать значение z для случая, когда одна из трех функций вернула nil? Легко. Нам поможет or:

Код:
x = foo(1) and y = bar(x) and z = buzz(x, y) or z = someDefaultValue
А если дефолтовое значение для z могут сформировать функции z01..z03 и они тоже могут вернуть ошибку? Не проблема, or'ов можно использовать несколько:

Код:
x = foo(1) and y = bar(x) and z = buzz(x, y) or z = z01() or z = z02() or z = z03() or someDefaultValue
Однако, в реальной жизни длинные цепочки or'ов практически не встречаются -- равно как и серии and'ов вперемешку с or'ами. Типичное использование -- несколько and'ов и опционально один замыкающий or.

Читается такое выражение всегда просто и понятно: "сделай это, это, это и это, ЛИБО сделай это".

Так что использовать стоит как &&/|, так и and/or. Но в совершенно разных целях.

Отправить "and или && ?" в Digg Отправить "and или && ?" в del.icio.us Отправить "and или && ?" в StumbleUpon Отправить "and или && ?" в Google Отправить "and или && ?" в VKontakte Отправить "and или && ?" в Facebook

Категории
Без категории

Комментарии