本文共 6684 字,大约阅读时间需要 22 分钟。
关于函数式编程(Functional programming,FP)
函数式编程(FP)是一种编程范式,它将计算过程视为函数运算,避免状态和数据的修改。与命令式编程相比,它更强调函数的运用。λ运算构建了函数式编程的基础。重要的函数式编程语言包括Lisp、Scheme、Erlang、Haskell、ML、OCaml等,微软则在2005年引入了F#。 此外,包括C/C++/C#/Python/Javascript等很多语言也提供了对FP的部分支持。由此我们可以得出一个结论,随着现实问题复杂度的增加,单一的编程范式很难满足需要了。我们需要对FP有更多的了解,问题是学习哪种语言呢?作为一个.NET程序员,我的答案是F#。使用F#,除了能借助FP的力量,最重要的一点是它跟.NET平台的无缝兼容,它可以轻松地与C#或VB.NET进行互操作,通过F#,我们手中的C#/VB.NET会变得更为强大。 本文尝试通过F#对FP的一些重要特征和属性做些介绍,包括函数(一等公民、高阶函数、柯里化、匿名函数、闭包)、避免副作用(对状态和数据的修改)、递归、惰性求值、模式匹配;然后讨论了FP对代码结构的影响。像Continuation和Monad留在以后的随笔中介绍。希望能增加您对FP的认识。函数是一等公民(First-class citizen) 这里的citizen也可换作object/value/entity,所谓一等公民是指那些在程序中可以无限制(相比于同一语言中的其它对象)使用的对象。在编程语言中,“函数是一等公民”意味着它可以: 1. 表示为匿名的文字值 2. 存储于变量中 3. 存储于数据结构中 4. 作为函数的参数进行传递 5. 作为函数的返回值 6. 在运行时进行构造 F#中的函数是一等公民,而在C#中,函数不是一等公民,比如我们不能把函数作为参数进行传递,也不能将其作为返回值,而对类则可以这么做。这种不同并不值得奇怪。如果我们把人类社会作为一个抽象来看,那么在它的不同实现中公民的等级也有所不同。在缅甸,和尚是一等公民,男人是二等公民,女人和尼姑是三等公民,人妖是四等公民,我们国家显然不是这样,但缅甸和中国的公民们大部分都能活得好好的。F# Code - First-class citizen #light let makeDerivative f (deltaX: float) = fun x -> (f(x + deltaX) - f(x)) / deltaX let cos = makeDerivative sin 0.000001 open System let writeLine input = print_any input Console.WriteLine() writeLine (cos 0.0) // ~= 1 writeLine (cos(Math.PI / 2.0)) // ~= 0 Console.Read()
F# Code - 函数柯里化 // val add : int -> int -> int let add a b = a + b // val increment : (int -> int) let increment = add 1
F# Code - 匿名函数 List.filter (fun i -> i % 2 = 0) [1 .. 20]
Type Infomation val it : (('a -> bool) -> 'a list -> 'a list)
Output [2; 4; 6; 8; 10; 12; 14; 16; 18; 20]
F# Code - 闭包(针对宿主函数的参数) #light open System let makePower power = let powerFn base = Math.Pow(base, power) powerFn let square = makePower 2.0 Console.WriteLine(square(3.0))
F# Code let cube = makePower 3.0
F# Code - 闭包(针对宿主函数的局部值) let makeIncrementer() = let n = ref 0 let increment() = n := !n + 1 !n increment let inc1 = makeIncrementer() let inc2 = makeIncrementer() Console.WriteLine(inc1()) // 1 Console.WriteLine(inc1()) // 2 Console.WriteLine(inc1()) // 3 Console.WriteLine(inc2()) // 1 Console.WriteLine(inc2()) // 2 Console.WriteLine(inc2()) // 3
F# Code - 递归 let rec factorial x = match x with | x when x < 0 -> failwith "value must be greater than or equal to 0" | 0 -> 1 | x -> x * factorial(x - 1)
XML Code - iBATIS.NET Lazyload
另一个是Lazy initialization,Singleton模式的一种实现方式用到了它:
C# Code - Singleton模式
F# Code - 惰性求值 let sixtyWithSideEffect = lazy(printfn "Hello, sixty!"; 30 + 30) print_endline "Force value the first time:" let actualValue1 = Lazy.force sixtyWithSideEffect print_endline "Force value the second time:" let actualValue2 = Lazy.force sixtyWithSideEffect
Output Force value the first time: Hello, sixty! Force value the second time:
F# Code - Lucas数 let rec luc x = match x with | x when x <= 0 -> failwith "value must be greater than zero" | 1 -> 1 | 2 -> 3 | x -> luc(x - 1) + luc(x - 2)
F# Code - 对元组应用模式匹配 let myOr b1 b2 = match b1, b2 with | true, _ -> true | _, true -> true | _ -> false
F# Code - 对列表应用模式匹配 let rec concatenateList list = match list with | head :: tail -> head @ (concatenateList tail) | [] -> []
F# Code - 对.NET类型应用模式匹配 let recognizeType (item : obj) = match item with | :? System.Int32 -> print_endline "An integer" | :? System.Double -> print_endline "A double" | :? System.String -> print_endline "A string" | _ -> print_endline "Unkown type"
参考:
《Foundations of F#》 by Robert Pickering 《Expert F#》 by Don Syme , Adam Granicz , Antonio Cisternino??本文转自一个程序员的自省博客园博客,原文链接:http://www.cnblogs.com/anderslly/archive/2008/10/26/fsharp-adventure-understanding-fp.html,如需转载请自行联系原作者。