F# 函数式编程之 - 乾坤大挪移
标题所说的 “乾坤大挪移” 是个夸张的说法,其实本文只是讲讲两种 “小挪移”。
其一,是指将面向对象编程中的 “对象” 换个位置,使其变成函数式编程中的函数的 “参数”,以便符合 F# 的编程风格。
之所以能进行这种挪移,是因为 F# 虽然以函数式为主,但已经被扩充成也支持对象(虽然不是 “纯函数式” 听起来不够酷,但更实用更好用了,如果 F# 是纯函数式我反而没兴趣)。
在 F# 里,字符串是对象,它有方法:
let hello = "hejjo".Replace("j", "l")
但这样操作,很不F#, 函数式编程的感觉出不来,所以我们下面来进行挪移:
let replace oldStr newStr (s:string) =
s.Replace(oldValue=oldStr, newValue=newStr)
这样我们得到了一个函数 replace, 它可以用 F# 的风格来操作:
"hejjo" |> replace "j" "l"
特别是与其他函数配合时,就更能体现 F# 风格的优雅:
// 例子出处: https://fsharpforfunandprofit.com/posts/partial-application/
let replace oldStr newStr (s:string) =
s.Replace(oldValue=oldStr, newValue=newStr)
let startsWith lookFor (s:string) =
s.StartsWith(lookFor)
let result =
"hello"
|> replace "h" "j"
|> startsWith "j"
["the"; "quick"; "brown"; "fox"]
|> List.filter (startsWith "f")
let compositeOp = replace "h" "j" >> startsWith "j"
let result = compositeOp "hello"
下面说说第二种挪移
在上一篇文章 F# 函数式编程之 - 柯里化 currying 中我们说过 “加号 + 本质上是一个函数, 而 x + y 其实是 (+) x y 的语法糖”, 在上面的代码里, |> 本质上也是一个函数,它的定义是:
let (|>) x fn = fn x
可见,它的作用只是简单地把函数 fn 的参数移到前面,加上类以于 + 号的语法糖,就形成了类似“管道”的功能,在上面的代码中我们已经看到,功能虽然简单,效果却很不错。
F# 甚至允许我们自己定义这种运算符,比如:
let (<<|) fn x = fn x
如上所示,我们自定义了一个 <<|, 它看起来作用不大,但它其实也很可爱,比如可以帮我们省略括号:
printf "%i" 1+2 // error
printf "%i" (1+2) // ok, using parens
printf "%i" <<| 1+2 // 也ok
F# 已经自带了 <|, 其定义与 <<| 完全一样,我在上面使用 <<| 只是为了说明 F# 允许用户自己定义运算符。
本文介绍了 F# 的两种 “小挪移”,一种是使对象变得更函数化,另一种是实现类似“管道”的功能,都是能让代码更优雅的小技巧。

浙公网安备 33010602011771号