F#学习之路(1)什么是函数式编程

     对于什么是函数式编程,这个是人云亦云。本文并不打算对此进行定义,而是希望与园子里的朋友们共同探讨这个话题,抛砖只为引玉。

     本文希望通过介绍F#中的语法,来了解函数式编程中专门的概念。

     1、维基百科给出的定义是:

函数式编程是种编程范式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ 演算(lambda calculus)。

而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。

     2、函数应该是高阶函数,可柯里化

     从维基百科定义可以看出,大家对函数式编程语言中,函数是一等公民(first class)这个概念是没有异议的。

     函数应该享受值的同等待遇,可以作为一个函数的参数,可以作为一个函数的返回值。

     函数应该是高阶函数。函数应该可柯里化(currying)。      

 

#light 
 
let p f= 
  
fun (x)->   f(x) 

let c t= 
   t+
10 

let r=p c 

let f=p (fun x-> "Hello," + x ) 

printfn 
"r=%d" (r 10 ); 

printfn 
"f=%s" (f "Lvxuwen")  

open System  

Console.ReadKey(
true


     

在F#中定义一个函数使用let 绑定表达式, 语法规则如下:

 

let函数名 参数1 参数2…参数n=函数体

 

F#参数之间用空格分隔,而不同于C#中用逗号分隔,参数也不用括号。

 

上面的F#代码第一行用#light指令,指出使用精简的语法规则,而不使用OCaml语法,OCaml语法使用begin end ;; ; in 等关键字来区分语句及作用域,使用#light指令后,虽然让我们可以使用简洁的语法,但这也意味着F#将利用缩进来区分语句及作用域。你可以在vss中 选择工具-选项-文本编辑器->F#-Tabs,设置Tab为插入空格,这可以让你方便的使用tab键缩进。另外,在vss中,你把上例"Hello," 改成中文"欢迎",如果在控制台中乱码,你可以选择 文件->高级保存选项->更改字符编码为中文简体GB2312或unicode编码。

 

3、纯函数式语言没有变量和副作用

这一点是函数式语言被认为编写并发程序最理想语言的重要原因。没有了变量和副作用,就不再有竞争资源的问题存在,就不再需要锁。

在F#中,let定义的标识符是表达式,并且一旦定义就不可更改。定义变量要使用专门的关键字mutable

 

let mutable var=20 
 
var
<-30

let constant=30 

constant=
40 

printfn 
"var=%d" var 

printfn 
"constant=%d" constant 
 

 

     变量var使用mutable关键字定义,并使用<-操作符赋值。而=操作符而被用做相等比较运算符,而constant使用<-,就会编译报错

     函数式编程中,函数用来定义规则,算法,如果一个函数使用同一个值传入,总是返回相等的结果,我们就说这个函数是没有副作用, 幂等的。 这样的函数最符合重用的原则,在高阶函数计算过程中可得到预知的结果。

   

     4、函数式编程函数应该是惰性求值的

     惰性求值(Lazy value),指的是表达式在需要时计算,而不是在定义时计算。这是支撑函数组合计算必要的条件,函数作为值传递过程中并不计算,只在明确调用时计算。

     

 

let la=lazy (printfn "%s" "Hello world";5)
[la;la] 
|> List.iter (fun la ->printfn "%d" (la.Force()))

 

     某些函数式语言,会将一些惰性操作作为普通求值过程的一部分,而F#则需要使用lazy来明确指定,表达式求值是惰性的。

    

      5、函数式编程中大量使用模式匹配

 

let t=true

match t with
true->printfn "it is true"
|false ->printfn "it is false"

 

     6、函数式编程中经常使用递归来代替循环。

   

let rec loop n f =
  
match f n with
  
|true->n
  
|_->f (n-1)

 

   

       总结:函数式编程语言中函数是一等公民,它使用高阶函数来组合函数,数据从函数中流入流出,函数式程序就是一个个函数的组合,数据被一个个函数处理, 或折分或组合生成新的数据结构。

      

       

    参考文献:

  1. 为什么函数式编程至关重要?
  2. 函数式编程另类指南
  3. 什么是monad?
标签: F#
posted @ 2008-07-29 21:38 lvxuwen 阅读(1795) 评论(10) 编辑 收藏

 回复 引用 查看   
#1楼2008-07-29 22:20 | 真见      
我也在关注F#,上次小试了一下,感觉CTP版的自动提示功能做的不是很好,而且我在里面可以把F#和C#的语言一起写。总体感觉很爽,呵呵。
 回复 引用 查看   
#2楼[楼主]2008-07-29 22:25 | lvxuwen      
@真见
是的,这个版本的自动提示还要有非常大的改进才行,最重要的是项目模板,MsBuild都没有好的支持,期待正式发行时这些都能够得到解决。

 回复 引用   
#3楼2008-08-02 11:40 | 同行友人[未注册用户]


楼主真是高见,跟小弟的想法真是不谋而合!


 回复 引用   
#4楼2008-08-06 13:33 | colder[未注册用户]
--引用--------------------------------------------------
真见: 我也在关注F#,上次小试了一下,感觉CTP版的自动提示功能做的不是很好,而且我在里面可以把F#和C#的语言一起写。总体感觉很爽,呵呵。
--------------------------------------------------------

CTP版本还没出吧?

 回复 引用   
#5楼2008-08-07 00:45 | f#中文站[未注册用户]
您的文章被转载,如有任何以疑问请访问 http://www.f-sharp.cn/bbs/dispbbs.asp?boardid=7&id=49
 回复 引用   
#6楼2008-08-07 14:36 | lionking.cn[未注册用户]
Curry化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数
 回复 引用 查看   
#7楼[楼主]2008-08-07 14:41 | lvxuwen      
@lionking.cn

currying柯里化从形式上讲将接受多个参数的函数转变成你已提供参数的剩余参数的函数,而并不仅仅是第一个参数的函数

 回复 引用 查看   
#8楼2008-09-01 13:12 | 簡簡單單..      
继续关注..
 回复 引用 查看   
#9楼[楼主]2008-09-07 16:06 | lvxuwen      
@簡簡單單..
谢谢关注,随着学习的深入,希望之后的文章对你更加有用

 回复 引用 查看   
#10楼2010-01-25 08:11 | TonyKent      
能讲一下第6个: 以递归代替循环的例子代码是什么意思吗?