F # условные выражения if ... then..еще возвращаясь блок или ()
условные выражения F#требуют проверки условия, ветви для true и ветви для false. Например:
let x =
if ("hello" = null)
then true
else false //error if else branch missing
однако, что-то становится странным, когда unit
, иначе ()
участвует.
let y =
if ("hello" = null)
then raise <| new ArgumentNullException()
else () //happy with or without else branch
и просто:
let z =
if ("hello" = null)
then ()
else () //happy with or without else branch
почему неelse
филиал требуется, когда unit
возвращается?
4 ответов
рассмотрим следующий код:
let f a = if a > 5 then true
если вы называете f 10
возвращает true
.
теперь спросите себя: что должно f 2
вернуться? Я знаю, ты скажешь false
, но откуда компилятор знает, что? Я имею в виду, это так же вероятно, что вы хотели, чтобы он вернулся true
в обоих случаях, не так ли? Или даже, возможно, врезаться в a <= 5
случае, кто знает?
Итак, чтобы программа была "полной" (т. е. содержала инструкции для того, что делать в каждой ситуации), вы всегда должны указать else
филиала.
unit
, однако,специальные.
возвращение unit
означает, что нет значимого возвращаемого значения. По существу unit
означает побочный эффект: это означает, что вещь, которая вернула его, должна была произвести некоторый эффект во внешнем мире. Поскольку F# не является чистым языком, такой unit
-возвращение вещи довольно вездесущи. Например, отладка logging:
let f x =
if x < 42 then printfn "Something fishy, x = %d" x
x + 5
С такими утверждениями нет никакой двусмысленности: всегда известно, что else
ветка предназначена для возврата ()
как хорошо. В конце концов, других значений unit
, там? В то же время, всегда добавляем else ()
в конце было бы очень утомительно и запутанно. Таким образом, в интересах удобства использования компилятор не требует else
филиал в этом конкретном случае.
В F# if
является выражением, а не утверждением. Каждое выражение должно возвращать значение. А как if
и else
необходимо вернуть тот же тип значения, потому что F# является строго типизированным языком. Так что, если нет else
ветвь, то по умолчанию она имеет тип unit
, а если if
возвращает значение типаunit
, тогда вам нужно иметь else
С тем же типом.
если убрать else
из первого фрагмента, это эквивалентно
let x =
if ("hello" = null)
then true
else ()
не typecheck.
почему? Я бы предположил, для совместимости с Программирования OCaml
на
else expr3
часть может быть опущена, и в этом случае она по умолчаниюelse ()
. (7.7.2)
вы можете думать о unit
-возвратить if
как эквивалент C-like if
сообщении в отличие от выражения.
вопрос уже ответил, поэтому я просто собираюсь продолжить свои собственные поверхностные наблюдения
в F# у нас нет операторов и выражений. В F# мы составляем вычисления, используя только выражения. Это хороший вещь.
в C#, где if
это утверждение имеет смысл
if(x)
{
return 1;
}
если x
истинно выполнение остановлено, и мы возвращаем вызывающему результат: 1
.
в F#, где if
выражение это означает, что if
должен представлять ценность независимо от того, какая ветвь была взята. Поэтому это имеет мало смысла
if x then 1 // What value should else branch evaluate to?
мы должны указать обе ветви
if x then 1 else 0
как показывают другие ответы, существует особый случай, когда else
опущен. The if
выражение произведет unit
value, самое близкое, что мы получаем к оператору в F#.
Потому что тип if
выражение является единицей ветвь "true" должна иметь тип unit
.
if x then () // This works
if x then () else () // This works
if x then 1 // This won't work, type mismatch