[Перевод] F#5: Операторы
Я намеревался написать ½ достойного поста в блоге об операторах F #, но потом я подумал, и, честно говоря, я не мог видеть слишком много достоинств в простом повторении того, что уже свободно доступно на MSDN, где перечисляются ВСЕ операторы F#.
Вы можете найти полный список всех операторов и символов F # на этой странице MSDN
Если вы перейдете по этой ссылке, первое, что вы поймете, это то, что в F# много операторов и символов, слишком много, чтобы я мог включить их в одно сообщение в блоге. Имея это в виду, я взял на себя намерение создать половину достойного поста в блоге об операторах и решил немного урезать сферу охвата, чтобы включить только обсуждение наиболее распространенных операторов, так что я думаю, Вы могли бы сказать, что этот будет только ¼ или 1/8 приличного поста, за что я смиренно извиняюсь.
Теперь, прежде чем мы начнем, я просто хотел сказать, что я собираюсь пройти только по наиболее распространенным операторам; Вам, скорее всего, придется изучить ссылку MSDN, которую я включил в начале этого поста, когда вы действительно начнете использовать F#, но сейчас я надеюсь, что тех, на которых мы остановимся, будет достаточно, чтобы мы начали.
Арифметические Операторы
+ Суммирование
Неконтролируемый. Возможное условие переполнения, когда числа суммируются, и сумма превышает максимальное абсолютное значение, поддерживаемое типом.
— Вычитание
Неконтролируемый. Возможное условие недостаточного заполнения, когда вычитаются неподписанные типы или когда значения с плавающей запятой слишком малы, чтобы быть представленными типом.
* Умножение
Неконтролируемый. Возможное состояние переполнения, если числа умножены, и произведение превышает максимальное абсолютное значение, поддерживаемое типом.
/ Деление
Деление на ноль вызывает исключение DivideByZeroException для целочисленных типов. Для типов с плавающей точкой деление на ноль дает вам специальные значения с плавающей точкой + Infinity или -Infinity. Также возможно условие недостаточного заполнения, когда число с плавающей запятой слишком мало, чтобы быть представленным типом.
% Модуль
Returns the remainder of a division operation. The sign of the result is the same as the sign of the first operand.
** Экспонирование
Возможное состояние переполнения, когда результат превышает максимальное абсолютное значение для типа. Оператор возведения в степень работает только с типами с плавающей точкой.
Демо
//Arithmetic operators
printfn "25 + 25 = %i" (25 + 25)
printfn "75 - 25 = %i" (75 - 25)
printfn "12 * 12 = %i" (12 * 12)
printfn "100 / 4 = %i" (100 / 4)
printfn "101 %% 10 = %i" (101 % 10)
printfn "2 ** 3 = %f" (2.0 ** 3.0)
И вот результат запуска:
Бинарные операторы
В следующей таблице показаны операторы двоичного сравнения, доступные для целочисленных типов и типов с плавающей точкой. Эти операторы возвращают значения типа bool.
= Равно
Это не оператор присваивания. Используется только для сравнения. Это универсальный оператор.
> больше чем
Это универсальный оператор.
<меньше чем
Это универсальный оператор.
> = больше или равно
Это универсальный оператор.
<= больше или равно
Это универсальный оператор.
<> Не равно
Это универсальный оператор.
//Binary operators
printfn "25 = 25 = %b" (25 = 25)
printfn "26 > 25 = %b" (26 > 25)
printfn "26 < 25 = %b" (26 < 25)
printfn "26 >= 25 = %b" (26 >= 25)
printfn "26 <= 25 = %b" (26 <= 25)
printfn "'a' <= 'b' = %b" ('a' <> 'b')
//how about a more complex example, a tuple
printfn "(1,'a') = (2,'a') = %b" ((1,'a') = (2,'a'))
printfn "(1,'a') = (1,'a') = %b" ((1,'a') = (1,'a'))
printfn "Some(1) = Some(2) = %b" (Some(1) = Some(2))
printfn "Some(2) = Some(2) = %b" (Some(2) = Some(2))
Булевы (Boolean) операторы
В следующей таблице приведены логические операторы, доступные на языке F #. Единственный тип, поддерживаемый этими операторами, это тип bool.
not
Булево отрицание
||
Логическое ИЛИ
&&
Логическое И
Вот небольшая демонстрация булевых операторов, перечисленных выше
//Boolean operators
printfn "not true = %b" (not true)
printfn "true || false = %b" (true || false)
printfn "true && true = %b" (true && true)
printfn "true && false = %b" (true && false)
Битовые операторы
В следующей таблице описаны побитовые операторы, которые поддерживаются для неупакованных целочисленных типов в языке F #.
&&&
Побитовый оператор «И». Биты в результате имеют значение 1 тогда и только тогда, когда соответствующие биты в обоих исходных операндах равны 1.
|||
Побитовый оператор «ИЛИ». Биты в результате имеют значение 1, если любой из соответствующих битов в исходных операндах равен 1.
^^^
Побитовый исключающий оператор «ИЛИ». Биты в результате имеют значение 1 тогда и только тогда, когда биты в исходных операндах имеют неравные значения.
~~~
Побитовый оператор отрицания. Это унарный оператор, который дает результат, в котором все 0 битов в исходном операнде преобразуются в 1 бит, а все 1 бит преобразуются в 0 бит.
<<<
Побитовый оператор левого сдвига. Результатом является первый операнд с битами, сдвинутыми влево на количество бит во втором операнде. Биты, сдвинутые с наиболее значимой позиции, не превращаются в наименее значимую позицию. Младшие значащие биты дополняются нулями. Тип второго аргумента — int32.
>>>
Побитовый оператор правого сдвига. В результате получается первый операнд с битами, сдвинутыми вправо на количество бит во втором операнде. Биты, сдвинутые из наименее значимой позиции, не превращаются в наиболее значимую позицию. Для беззнаковых типов старшие биты дополняются нулями. Для типов со знаком наиболее значимые биты дополняются единицами. Тип второго аргумента — int32.
//Bit shift operators
//&&& and
printfn "2 &&& 4 (which is 0010 &&& 0100, should be 0) = %X" (2 &&& 4)
printfn "2 &&& 3 (which is 0010 &&& 0011, should be 2) = %X" (2 &&& 3)
//||| or
printfn "2 ||| 4 (which is 0010 ||| 0100, should be 6) = %X" (2 ||| 4)
printfn "2 ||| 3 (which is 0010 ||| 0011, should be 3) = %X" (2 ||| 3)
//^^^ xor
printfn "2 ^^^ 4 (which is 0010 ^^^ 0100, should be 6) = %X" (2 ^^^ 4)
printfn "2 ^^^ 3 (which is 0010 ^^^ 0011, should be 1) = %X" (2 ^^^ 3)
//^^^ negate
printfn "~~~4 (which is not 0100, should be 1011 (B hex), or 11 decimal) = %X" (~~~4)
//<<< bit shift left
printfn "4 <<< 1 (which is 0100 <<< by 1 place left , should be 1000 (8 hex), or 8 decimal) = %X" (4 <<< 1)
//>>> bit shift right
printfn "4 >>> 1 (which is 0100 >>> by 1 place right , should be 0010 (2 hex), or 2 decimal) = %X" (4 >>> 1)
Перегрузка оператора
Как я уже упоминал, будут времена, когда вам нужно будет реализовать собственную операторскую логику. В других языках .NET это может быть достигнуто путем предоставления собственных перегрузок операторов. Не удивительно, что вам нужно сделать то же самое в F#. Я пока не хотел вдаваться в классы и ОО, но это как бы соответствует текущему обсуждению, поэтому давайте посмотрим, как вы можете реализовать свои собственные операторы в F#.
Я снова украл это из MSDN. Следующий код иллюстрирует векторный класс, который имеет только два оператора: один для унарного минуса и один для умножения на скаляр. В этом примере необходимы две перегрузки для скалярного умножения, поскольку оператор должен работать независимо от порядка появления вектора и скаляра.
type Vector(x: float, y : float) =
member this.x = x
member this.y = y
static member (~-) (v : Vector) =
Vector(-1.0 * v.x, -1.0 * v.y)
static member (*) (v : Vector, a) =
Vector(a * v.x, a * v.y)
static member (*) (a, v: Vector) =
Vector(a * v.x, a * v.y)
override this.ToString() =
this.x.ToString() + " " + this.y.ToString()