[Перевод] 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)


И вот результат запуска:

image

Бинарные операторы


В следующей таблице показаны операторы двоичного сравнения, доступные для целочисленных типов и типов с плавающей точкой. Эти операторы возвращают значения типа 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))


image

Булевы (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)


image

Битовые операторы


В следующей таблице описаны побитовые операторы, которые поддерживаются для неупакованных целочисленных типов в языке 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)


image

Перегрузка оператора


Как я уже упоминал, будут времена, когда вам нужно будет реализовать собственную операторскую логику. В других языках .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()

© Habrahabr.ru