编程语言的发展趋势及未来方向(3):函数式编程(转)

这是Anders Hejlsberg(不用介绍这是谁了吧)在比利时TechDays 2010所做的开场演讲。 由于最近我在博客上关于语言的讨论比较多,出于应景,也打算将Anders的演讲完整地听写出来。在上一部分中,Anders阐述了他眼中声明式编程的理 念及DSL,并演示C#中一种内部DSL的形式:LINQ。在这一部分中,Anders谈及了声明式编程的另一个重要组成部分:函数式编程,并使 用.NET平台上的函数式编程语言F#进行了演示。

如果没有特别说明,所有的文字都直接翻译自Anders的演讲,并使用我自己的口语习惯表达出来,对于Anders的口误及反复等情况,必要时在译文中自然也会进行忽略。为了方便理解,我也会将视频中关键部分进行截图,而某些代码演示则会直接作为文章内容发表。

(听写开始,接上篇)

编程语言的发展趋势及未来方向(3):函数式编程(转)

关于声明式编程的还有一部分重要的内容,那便是函数式编程。函数式编程已经有很长时间的历史了,当年LISP便是个函数式编程语言。除了LISP以外我们还有其他许多函数式编程语言,如APL、Haskell、Scheme、ML等等。关于函数式编程在学术界已经有过许多研究了,在大约5到10年前许多人开始吸收和整理这些研究内容,想要把它们融入更为通用的编程语言。现在的编程语言,如C#、Python、Ruby、Scala等等,它们都受到了函数式编程语言的影响。

编程语言的发展趋势及未来方向(3):函数式编程(转)

我想在这里先花几分钟时间简单介绍一下我眼中的函数式编程语言。我发现很多人听说过函数式编程语言,但还不十分清楚它们和普通的命令式编程语言究竟 有什么区别。如今我们在使用命令式编程语言写程序时,我们经常会写这样的语句,嗨,x等于x加一,此时我们大量依赖的是状态,可变的状态,或者说变量,它 们的值可以随程序运行而改变。

可变状态非常强大,但随之而来的便是叫做“副作用”的问题。在使用可变状态时,你的程序则会包含副作用,比如你会写一个无需参数的void方法,然 后它会根据你的调用次数或是在哪个线程上进行调用对程序产生影响,因为void方法会改变程序内部的状态,从而影响之后的运行效果。

而在函数式编程中则不会出现这个情况,因为所有的状态都是不可变的。你可以声明一个状态,但是不能改变这个状态。而且由于你无法改变它,所以在函数 式编程中不需要变量。事实上对函数式编程的讨论更像是数学、公式,而不像是程序语句。如果你把x = x + 1这句话交给一个程序员看,他会说“啊,你在增加x的值”,而如果你把它交给一个数学家看,他会说“嗯,我知道这不是true”。

编程语言的发展趋势及未来方向(3):函数式编程(转)

然而,如果你给他看这条语言,他会说“啊,y等于x加一,就是把x + 1的计算结果交给y,你是为这个计算指定了一个名字”。这时候在思考时就是另一种方式了,这里y不是一个变量,它只是x + 1的名称,它不会改变,永远代表了x + 1。

所以在函数式编程语言中,当你写了一个函数,接受一些参数,那么当你调用这个函数时,影响函数调用的只是你传进去的参数,而你得到的也只是计算结 果。在一个纯函数式编程语言中,函数在计算时不会对进行一些神奇的改变,它只会使用你给它的参数,然后返回结果。在函数式编程语言中,一个void方法是 没有意义的,它唯一的作用只是让你的CPU发热,而不能给你任何东西,也不会有副作用。当然现在你可能会说,这个CPU发多少热也是一个副作用,好吧,不 过我们现在先不讨论这个问题。

编程语言的发展趋势及未来方向(3):函数式编程(转)

这里的关键在于,你解决问题的方法和以前大不一样了。我这里还是用代码来说明问题。使用函数式语言写没有副作用的代码,就好比在Java或C#中使用final或是readonly的成员。

例如这里,我们有一个Point类,构造函数接受x和y,还有一个MoveBy方法,可以把一个点移动一些位置。 在传统的命令式编程中,我们会改变Point实例的状态,这么做在平时可能不会有什么问题。但是,如果我把一个Point对象同时交给3个API使用,然 后我修改了Point,那么如何才能告诉它们状态改变了呢?可能我们可以使用事件,blablabla,如果我们没有事件,那么就会出现那些不愉快的副作 用了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzsfxz.html