F#有三元运算符?:吗?

50

我正在从C#学习F#,我刚尝试编译这样一个表达式

let y = Seq.groupBy (fun x -> (x < p ? -1 : x == p ? 0: 1))

但是看到了“表达式中的意外整数字面值”。F#有三元运算符吗?如果没有,我应该使用什么替代品?


2
不相关,但您可能只想使用x.CompareTo(p) https://msdn.microsoft.com/en-us/library/43hc6wht(v=vs.110).aspx。这适用于大多数支持`<==`操作符的类型... - Reed Copsey
@Reed Copsey 这与我学习的目标有一定关联,但确实有些离题了。 :) - Tim Lovell-Smith
是的,与三元能力无关 - 但在我看来,写起来更加简洁 (fun x -> x.CompareTo(p)) :) - Reed Copsey
2
@ReedCopsey 在 F# 中,您可以使用函数 compare,因此 (fun x -> compare p x) 也可以写成 compare p,但 (fun x -> compare x p) 变成了 ((˜-) >> compare -p),这比 lambda 表达式更难读 ;) - Gus
4个回答

73

是的,它被称为if .. then .. else

事实上,在 F# 中一切都是表达式,甚至包括 if .. then .. else 块。

在 C# 中:var x = true ? 0 : 1;

在 F# 中:let x = if true then 0 else 1

所以在你的情况下:

let y = Seq.groupBy (fun x -> if x < p then -1 else if x = p then 0 else 1)

你可以使用elif来简化它。

let y = Seq.groupBy (fun x -> if x < p then -1 elif x = p then 0 else 1)

在F#中特别是当你有两个以上的情况需要考虑时,另一个可以考虑的选项是模式匹配:

let f p x =
    match x with
    | x when x < p -> -1
    | x when x = p ->  0
    | _ -> 1

let y = Seq.groupBy (f p)

但在你的特定情况下,我会使用if .. then .. elif .. then语句。

最后请注意,测试等号运算符是=而不是C#中的==


在表达式 if x < p then -1 elif x = p then 0 else 1 中,我们如何知道else属于哪个“if”? - Enigmativity
它对应于先前的if或elif。这与在C#中组合许多?:相同。 - Gus
1
由于if..then..else是一个表达式,所以thenelse分支需要具有相同的类型。只有当then子句计算为unit时,才能跳过else - Christopher Stevenson
是的。在C#中,? :也需要相同类型。 - Gus
3
@Enigmativity 实际上它属于它们两个。if表达式可以有零个或多个elif分支,因此if a then x elif b then y else z是一个单独的if表达式。另一方面,if a then x else if b then y else c是一个if表达式,其中then分支本身是第二个if表达式。与无法编译的if a then if b then x else y else z相比,then分支包含一个if表达式,需要将if表达式放在括号中:if a then (if b then x else y) else z。这与C#条件运算符不同。 - phoog

9
如果你想节省打字时间,你可以定义自己的。
let (?=) (q: bool) (yes: 'a, no: 'a) = if q then yes else no

请注意,您不能在运算符中使用冒号,所以 ?= 是你能得到的最接近的符号。
用法:maybe ?=(“true”,“false”)

你可以摆脱所有的类型注释。 - John Palmer
让 (?=) (q) (是,否) = 如果 q 则 是 否则 否 - Chris Woodward
12
请注意:无论条件如何,这将急切地评估真假两个面!也就是说,if true then printf "a" else printf "b" 只会打印 a,但是 true ?= (printf "a", printf "b") 将打印 ab! - piaste

6
您也可以使用带卫语的函数匹配来实现此功能:
    let y = Seq.groupBy  (function |x when x < p -> -1
                                   |x when x = p -> 0
                                   |_ -> 1)

模式匹配可能看起来比三元运算符长,但当逻辑变得更加复杂时,它们更容易阅读。


4

如果您想了解F#中有关C#表达式和语句的更多示例,可以参考此页面。例如:

三元运算符

C# has the ternary operator "?:" for conditional expressions:

condition ? trueVal : falseVal 

F# has the same operator, but its name is if-then-else:

if condition then trueVal else falseVal

(Note that "if" is used much less frequently in F# than in C#; in F#, many conditionalexpressions are done via pattern-matching rather than if-then-else.)

Switch statement

C# has a switch statement. It looks something like this:

switch (x) 
{ 
    case 1: 
        SomeCode(); 
        break; 
    default: 
        SomeCode(); 
        break; 
} 

In F#, this is just one of many things that pattern matching expresses more succinctly:

    match x with 
     | 1 -> SomeCode() 
     | _ -> SomeCode()  // _ is a ‘catch all’ default

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接