F # как написать пустое утверждение - PullRequest
17 голосов
/ 24 апреля 2010

Как я могу написать неоперативный оператор на F #?

В частности, как я могу улучшить второе предложение следующего оператора сравнения:

match list with
    | [] -> printfn "Empty!"
    | _ -> ignore 0

Ответы [ 2 ]

30 голосов
/ 24 апреля 2010

Использовать единицу для пустого побочного эффекта:

match list with
  | [] -> printfn "Empty!"
  | _ -> ()
16 голосов
/ 24 апреля 2010

Ответ от Stringer , конечно, правильный. Я подумал, что было бы полезно уточнить, как это работает, потому что "()" на самом деле не пустой оператор или пустой побочный эффект ...

В F #, каждый допустимый фрагмент кода является выражением . Конструкции типа let и match состоят из нескольких ключевых слов, шаблонов и нескольких подвыражений. Грамматика F # для let и match выглядит следующим образом:

<expr> ::= let <pattern> = <expr>
           <expr>
       ::= match <expr> with
           | <pat> -> <expr>

Это означает, что тело let или тело предложения match должно быть некоторым выражением. Это может быть вызов некоторой функции, такой как ignore 0, или это может быть какое-то значение - в вашем случае это должно быть выражение типа unit, поскольку printfn ".." также имеет тип unit.

Тип unit - это тип, который имеет только одно значение, которое записывается как () (и это также означает пустой кортеж без элементов). Это действительно немного похоже на void в C # за исключением того, что void не имеет каких-либо значений.

Кстати: следующий код может выглядеть как последовательность операторов, но также является выражением:

printf "Hello "
printf "world"

Компилятор F # неявно добавляет ; между двумя строками, а ; является оператором последовательности, который имеет следующую структуру: <expr>; <expr>. Требуется, чтобы первое выражение возвращало unit и возвращало результат второго выражения.

Это немного удивительно, когда вы начинаете с C #, но это делает язык на удивление элегантным и лаконичным. Это никак не ограничивает вас, например, вы можете написать:

if (a < 10 && (printfn "demo"; true)) then // ...

(Этот пример не очень полезен - просто демонстрация гибкости)

...