递归
运算符
Function Application
模式匹配
控制流
递归
F#中使用递归函数,需要用到rec关键字,表示(Recursion)。看个例子就明白了,计算斐波那契数。
let
rec
fib x
=
match x with
| 1 -> 1
| 2 -> 1
| x -> fib (x - 1 ) + fib (x - 2 )
printfn "(fib 2) = %i" (fib 2 )
printfn "(fib 6) = %i" (fib 6 )
printfn "(fib 11) = %i" (fib 11 )
match x with
| 1 -> 1
| 2 -> 1
| x -> fib (x - 1 ) + fib (x - 2 )
printfn "(fib 2) = %i" (fib 2 )
printfn "(fib 6) = %i" (fib 6 )
printfn "(fib 11) = %i" (fib 11 )
运算符
和C#一样,F#的运算符也能支持很多类型的操作。但是有一点要注意,C#中运算符两边的操作数类型可以不一致,但是F#中操作数类型必须一致,否则编译器报错。
F#中,也可以重新定义操作符,将操作符加上括号,该操作符就变成一个值了。比如下面的代码:
let result = (+) 1 1
此处 (+)就是一个方法的名字,后面跟着2个参数。
也可以自定义运算符,比如:
let
(
+
)
a b
=
a
-
b
printfn
"%i"
(
1
+
1
)
算出的结果是0
let
(
+*
)
a b
=
(a
+
b
)
*
a
*
b
printfn "(1 +* 2) = %i" ( 1 +* 2 )
printfn "(1 +* 2) = %i" ( 1 +* 2 )
结果是6
Function Application
Function Application也称做function composition 或者composing functions(复合函数)。个人认为是一个语法糖。
采用符号|>来复合函数。定义如下,let (|>) x f = f x
举个例子
let result = System.Math.Cos 0.5
转换一下就是
let result = 0.5 |> System.Math.Cos
在某些情况下,这个功能很有用,比如下面的代码:
let add x y = x + y
let result = add 6 7 |> add 4 |> add 5
模式匹配
就是类似C#中的switch语句,但是在F#中,比C#更加灵活强大。
看几个例子就明白了。
// definition of Lucas numbers using pattern matching
let rec luc x =
match x with
| x when x <= 0 -> failwith "value must be greater than 0"
| 1 -> 1
| 2 -> 3
| x -> luc ( x - 1 ) + luc ( x - 2 )
// call the function and print the results
printfn "(luc 2) = %i" ( luc 2 )
printfn "(luc 6) = %i" ( luc 6 )
printfn "(luc 11) = %i" ( luc 11 )
printfn "(luc 12) = %i" ( luc 12 )
let rec luc x =
match x with
| x when x <= 0 -> failwith "value must be greater than 0"
| 1 -> 1
| 2 -> 3
| x -> luc ( x - 1 ) + luc ( x - 2 )
// call the function and print the results
printfn "(luc 2) = %i" ( luc 2 )
printfn "(luc 6) = %i" ( luc 6 )
printfn "(luc 11) = %i" ( luc 11 )
printfn "(luc 12) = %i" ( luc 12 )
可以忽略第一个|,如果要匹配的逻辑很短小的话,并且可以写在一行上。而且,可以使用"_"作为通配符。
let
booleanToString x
=
match x with false -> "False" | _ -> "True"
printfn "%s" (booleanToString true )
match x with false -> "False" | _ -> "True"
printfn "%s" (booleanToString true )
也可以把2个匹配条件写在一起。
let
stringToBoolean x
=
match x with
| "True" | "true" -> true
| "False" | "false" -> false
| _ -> failwith "unexpected input"
printfn "(stringToBoolean \"True\") = %b" (stringToBoolean "True" )
match x with
| "True" | "true" -> true
| "False" | "false" -> false
| _ -> failwith "unexpected input"
printfn "(stringToBoolean \"True\") = %b" (stringToBoolean "True" )
也可以同时匹配多个参数。
let
myOr b1 b2
=
match b1, b2 with
| true, _ -> true
| _, true -> true
| _ -> false
let myAnd p =
match p with
| true, true -> true
| _ -> false
printfn "(myOr true false) = %b" (myOr true false )
printfn "(myOr false false) = %b" (myOr false false )
printfn "(myAnd (true, false)) = %b" (myAnd ( true, false ) )
printfn "(myAnd (true, true)) = %b" (myAnd ( true, true ) )
match b1, b2 with
| true, _ -> true
| _, true -> true
| _ -> false
let myAnd p =
match p with
| true, true -> true
| _ -> false
printfn "(myOr true false) = %b" (myOr true false )
printfn "(myOr false false) = %b" (myOr false false )
printfn "(myAnd (true, false)) = %b" (myAnd ( true, false ) )
printfn "(myAnd (true, true)) = %b" (myAnd ( true, true ) )
由于匹配语句很常用,因此F#提供了
快捷模式。如果一个函数主要使用匹配值功能,那么就可以使用这个快捷语法。使用关键字function,把模式放在函数参数的地方,用“|”分割匹配规则。如下代码:
// concatenate a list of strings into single string
let rec conactStringList =
function head :: tail -> head + conactStringList tail | [ ] -> ""
// test data
let jabber = [ "'Twas " ; "brillig, " ; "and " ; "the " ; "slithy " ; "toves " ; "..." ]
// call the function
let completJabber = conactStringList jabber
// print the result
printfn "%s" completJabber
let rec conactStringList =
function head :: tail -> head + conactStringList tail | [ ] -> ""
// test data
let jabber = [ "'Twas " ; "brillig, " ; "and " ; "the " ; "slithy " ; "toves " ; "..." ]
// call the function
let completJabber = conactStringList jabber
// print the result
printfn "%s" completJabber
控制流
F#中,if语句的返回值必须是同一种类型
let
result
=
if System. DateTime. Now. Second % 2 = 0 then
"heads"
else
"tails"
printfn "%A" result
let result1 =
if System. DateTime. Now. Second % 2 = 0 then
box "heads" //必须是同一种类型,装箱操作;
else
box false
printfn "%A" result1
if System. DateTime. Now. Second % 2 = 0 then
"heads"
else
"tails"
printfn "%A" result
let result1 =
if System. DateTime. Now. Second % 2 = 0 then
box "heads" //必须是同一种类型,装箱操作;
else
box false
printfn "%A" result1
转载于:https://blog.51cto.com/cnn237111/897026