问题
I'm learning F# coming from C# and I've just tried compiling an expression like
let y = Seq.groupBy (fun x -> (x < p ? -1 : x == p ? 0: 1))
but see 'unexpected integer literal in expression'. Does F# have a ternary operator? If not, what should I use instead?
回答1:
Yes, it's called if .. then .. else
In fact in F# everything is an expression, even an if .. then .. else
block.
In C# var x = true ? 0 : 1;
In F# let x = if true then 0 else 1
So in your case:
let y = Seq.groupBy (fun x -> if x < p then -1 else if x = p then 0 else 1)
you can shorten it a bit with elif
let y = Seq.groupBy (fun x -> if x < p then -1 elif x = p then 0 else 1)
Another option to consider in F# specially when you have more than 2 cases is pattern matching:
let f p x =
match x with
| x when x < p -> -1
| x when x = p -> 0
| _ -> 1
let y = Seq.groupBy (f p)
But in your particular case I would use the if .. then .. elif .. then.
Finally note that the test-equality operator is =
not ==
as in C#.
回答2:
You can also implement this using pattern matching with function using guards:
let y = Seq.groupBy (function |x when x < p -> -1
|x when x = p -> 0
|_ -> 1)
Pattern matches may seem longer ternary operator but they are much easier to read when logic gets more complex.
回答3:
If you want to save the typing you can define your own
let (?=) (q: bool) (yes: 'a, no: 'a) = if q then yes else no
Note that you can't use : in operators so ?= is the nearest you can get.
Usage: maybe ?= ("true", "false")
回答4:
For more examples of C# expressions and statements in F# you can refer to this page. For example:
Ternary operator
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
来源:https://stackoverflow.com/questions/28551938/does-f-have-the-ternary-operator