Первая часть головоломки - понять, что a &-= b
- это просто синтаксический сахар для a = a &- b
. Или, в общем, a op= b
- это синтаксический сахар для a = a op b
. Ссылка на язык подробно описывает это в разделе «Комбинированные назначения» в Операторы .
Теперь нам нужно спросить, что такое &-
и чем оно отличается от -
? К сожалению, API-документы на момент написания очень тихо об этом. Справочник по языку также не очень сложен, но на той же странице Операторы, что и выше, мы можем найти:
-
вычитание &-
вычитание переноса
Так что же такое вычитание переноса? Ну, у Кристалла есть фиксированные размеры чисел. Таким образом, они могут переполниться или потеряться в этом случае. Что это обозначает? Давайте рассмотрим пример:
# We have something to sell! Let's keep track of how many!
# It doesn't really make sense to have negative something left,
# so an unsigned integer ought to this.
items_left = 2u32
# Just made the first sell! Let's remember
items_left -= 1
# People seem to actually like this
items_left -= 1
# I could do this all day!
items_left -= 1 # => Unhandled exception: Arithmetic overflow (OverflowError)
# Oh no what happend?
Итак, программа попыталась на go ниже 0
, что тип UInt32
не может представлять. Это снизилось. Если Crystal не выполнит эту проверку, процессор с радостью обернется целочисленным типом, и мы получим 4294967295
in items_left
(UInt32::MAX
).
Но иногда, в коде низкого уровня, это поведение то, что мы хотим. Например, если мы подсчитываем некоторую статистику c, скажем, отправленные пакеты, если этот счетчик переполнен или переполнен, мы не хотим, чтобы в этом случае произошел сбой программы, обертывание - это нормально. Или, может быть, у нас есть некоторый чувствительный к производительности код, и мы уверены, что он работает правильно и никогда не будет переполнен, поэтому мы не хотим платить дополнительные циклы ЦП, проверяя, не переполнилась ли операция.
Для этих случаев есть математические операторы с префиксом &
. Они просто выполняют операцию без какой-либо проверки переполнения. Если бы мы использовали &-
вместо -
в приведенном выше примере, у нас было бы 4294967295
в items_left
сейчас.
В общем, вы знаете, если вам нужны операторы переноса или вы получаете выгоду , Сомневаешься, просто притворись, что их не существует.