代码改变世界

说的都是概念——有关编程范式

2005-12-17 17:41 FantasySoft 阅读(...) 评论(...) 编辑 收藏

        在Python中,lambda是一个有趣的关键字,它用于定义简单的匿名函数。匿名函数的概念,是指没有与特定变量绑定的函数。也就是除了定义的那一刻可以引用该函数之外,你无法通过任何方式再次引用它了。这类似于我们熟知的立即数,因此我给由lambda语法定义的匿名函数起了个新名字:立即函数。存在即是真理,Python中引入了lambda语法,引入了匿名函数的概念,它所坚持的真理又是什么呢?
       
假设我们已经有了这样一个函数定义:

def func(x, y):
    
print x, y


在我们调用一个函数或者说一个方法的时候,调用方式可以是这样的:

a, b = "Hello"1
func(a, b)


也可以是这样的:

func("Hello"1)


那么这两种调用方式有什么不同呢?是的,这个例子真的太简单了,以至于你会马上发现它们之间的
不同,也正是由于它太简单了,你也会觉得比较两者的区别简直就是在钻牛角尖。别着急,这简单的背后隐含的内容可不简单。很明显,第一种调用方式比第二种多出了两个变量,也多出两个赋值的语句(statement),在函数调用的时候通过变量引用具体的值;而第二种方式则是直接以具体的值作为参数,没有变量与这些值绑定。如果"Hello"和1使用的次数不多,那么第二种直接的调用方式会更为高效,毕竟在某个(可能会是全局)范围内,你不需要将"Hello"和1绑定到某个变量,所开辟的内存空间也可以及早地被回收,更重要的是减少不必要的错误!在一个复杂的应用程序中,变量就如同于一个状态机,变量的改变有些时候是程序能够执行的驱动力,有时候则是程序正常执行的绊脚石。作为程序员,我们需要跟踪并熟知这些变量的状态(当前值是什么),否则就很容易编写出错误的程序,而在现实中,大多数程序错误都会来源于你所使用的变量值与你所预期的不一致。说到这里,你应该会想起使用Debugger调试程序的痛苦经历,也会想起为一些让人迷惑的变量增加一个个Watch以便确定它们某个状态值的繁琐过程,我想,你也应该明白“减少不必要的错误”指的是什么了:减少变量定义,减少statement,也就减少了side-effect,最终减少了程序员的负担。在这里,我们引出了另外一个需要关注的新概念——side-effect
        其实side-effect的含义在上面的文字中已经隐约提到了(上文红色字的部分),以下是引用自
Wikipedia的定义:In computer science, a function is said to produce a side-effect if it modifies some state other than its return value。side-effect是一把双刃剑,不同的语言对它有着不同的态度:Imperative programming Language(命令式编程语言,譬如C++、C#和汇编)是充分利用了side-effect来驱动程序的运行;而Declarative programming Language(声明式编程语言,譬如SQL和Haskell。Functional programming Language是它的重要组成部分)则是在最大程度上限制side-effect。这里又是三个新的概念,大家从给出例子中应该可以对这两种语言有一个感性的认识,我就不做解释了,以上给出的链接提供了更为详细的内容。
        对于命令式编程语言,大家肯定是最为熟悉的,因为我敢说99%的程序员都在使用命令式编程语言。
那么你对以上提到的利用side-effect驱动程序的运行的理解又有多少呢?其实,这并非是一个深奥的问题,因为这在程序中几乎无所不在,一个很简单的例子就是循环中用于条件判断的变量,如果我们恰当地定义了循环的起始和终止条件,那么我们就会得到一个预期的有限次数的循环,一旦定义错误,死循环也就不可避免了。而对于声明式编程而言,大家可能就相对了解得比较少了,可能对Functional Programming Language了解得更多一些。Functional Programming Language所关注的是定义,也就是程序需要处理的内容,而不是如何去处理,关注的是what,而非how。在最为纯粹的Functional Programming中,定义就是程序的全部。说到这里,你或许会像我第一次接触Functional Programming的时候一样,觉得很诧异,光有定义的程序能够被执行吗?想想一条SQL的执行,解答疑惑也就有了线索。是的,当定义碰上分析定义的Engine,定义也就有了生命。限制side-effect是Functional Programming Language的重要特性之一,而限制side-effect的最简单手段就是减少变量的使用,减少statement。在真正纯粹的Function Programming Language中,是不会有statement存在的。
        好了,要提到的概念都陆续登场了,最开始提到的问题还是给出答案呢。啊,你忘了是什么问题啦?
嗯,嗯,看来我真的太罗嗦了。不过,你在回头看看问题的时候,你的心里是不是也有了答案呢?
        在Python中OO机制虽然足够强大,但由于Python本身更加注重Functional Programming,function才
是名副其实的first class。Python中的function几乎无所不能,一个Python程序的功能几乎都依赖于function的定义,而function本身更是可以操作其他function,甚至还能动态生成class!然而在没有lambda之前,function是离不开def的,def就相当于function的statement,阻碍着Python充当一个纯粹Functional Programming的角色。因此,利用lambda将function平民化,让function也能像上面"Hello"和1那样自然地扮演function参数的角色,这无疑是一个漂亮的设计。依靠lambda,Python可以做到最纯粹的Functional Programming——这就是问题的答案。以下这篇文章来自著名的Charming Python系列:Functional Programming In Pytthon,它会给你更多的启示。我相信你在阅读的过程中会惊喜的发现,程序原来也可以这样写的。
         说的都是概念,看完以后可别忘了练一练。:)