[原]重新开始学习Scheme(1)

7244阅读 7评论2012-02-22 fera
分类:Python/Ruby

函数式编程(Functional Programming)是在MIT研究人工智能(Artificial Intelligence)时发明的,其编程语言为Lisp。确切地说,Lisp是一个语言家族,包括无数的方言如:Scheme、Common Lisp、Haskell……等等。

最后一次学习Scheme已经是去年7月份的事情了。本来只是出于兴趣,以及拓宽自己思路的目的来学习。未曾想,由于工作需要,Scheme编程已经成为一个必备的技能了。其实这里面也由办公室政治的原因,因为我本来是做驱动开发的。现在PO和Boss已经开始对立了,因此出现了PO想让我做驱动,而Boss更倾向于根据自己的亲信的兴趣爱好来决定是否要挤掉我的驱动开发岗位。扯得有点远了,生活就是如此,不能事事如意。还是那句话,做一天和尚就撞好一天钟。

出于兴趣或者因为工作需要而开始学习一项技能时,学习方法的差异相当的大。出于兴趣时,完全可以根据自己的喜好、时间、背景知识等情况来决定关注点,并可以充分研究自己所关心的地方。然而,为了工作而学习时,就需要综合考虑诸多因素,比如项目的计划、对技能熟悉程度的要求等来决定学习的重点。这种方式便是所谓"On job training",或者叫做通过实践来学习。这种方式的好处就是可以迅速的开始使用某项技能,缺点也很明显,那就是很难有时间让你去思考这项技能的本质。市场上充斥着"XXX天学会XXX"的书就不足为怪了。

说了这么多闲话,还是言归正传吧。先来看看Scheme的基本概念。

第一个,也是最基本的概念:S-expression(Symbolic-expression,符号表达式),最初适用于表示数据的,后来被用作Lisp语法的基础。它是一个原子,或者一个(s-expr . s-expr)的表达式。后者为一个pair。所谓list,就是由pair组成的:(x . (y . z))就是一个list,它可以被简写为(x y z)。原子主要是指数字、字符串和名字。S-expression是Lisp求值器能处理的语法形式。

第二个,则是一等函数(first-class funciton)。它是first-class object的一种,是编程语言里的一等公民(first-class citizen)。first-class的含义是,当一个对象满足如下条件时:
1. 可以在运行时构造
2. 可以当做参数传递
3. 可以被当做返回值返回
4. 可以赋值给变量
便可以被成为first-class object。
例如:
  1. (define (my-cons x y)
  2.   (lambda (f)
  3.     (f x y)
  4.     )
  5.   )

  6. (define (my-car lst)
  7.   (lst
  8.    (lambda (x y) x)
  9.    )
  10.   )

  11. (define (my-cdr lst)
  12.   (lst
  13.    (lambda (x y) y)
  14.    )
  15.   )
对其的使用如下:
  1. > (define pair1 (my-cons 10 11))
  2. > pair1
  3. #<procedure>
  4. > (my-car pair1)
  5. 10
  6. > (my-cdr pair1)
  7. 11
根据上述规则,很显然,C/C++的函数就不是一等函数,因为他们不满足第一个条件。在函数式编程中,使用另一个函数作为参数,或者返回一个函数,或者二者兼有的函数称为高阶函数(High-order function)。既然说到高阶函数,就不能不说词法闭包(Lexical Closure,或者简称为闭包closure)。闭包指的是函数本身以及其自由变量(或非本地变量)的引用环境一起构成的结构,其允许函数访问处于其词法作用域(lexical scope)之外的变量,例如:
  1. (define closure-demo
  2.   (let ((y 5))
  3.     (lambda (x)
  4.       (set! y (+ y x))
  5.       y)
  6.     )
  7.   )
这里需要注意闭包与匿名函数的区别。

第三个基础概念便是递归。其实对于递归没有太多可说的,但一定要注意的是尾递归(tail-recursion)。尾递归使得用递归的形式实现递推成为可能。

第四个是词法作用域。

第五个是lambda算子(lambda calculus)

第六个是块结构

第七个是一级续延(first-class continuation)

第八个是宏(卫生宏:展开时能够保证不使用意外的标示符)

其中,有些基本概念又能引申出一些新的概念。后面这些基本概念(4~8),留到以后讨论。

另外,在可以找到一些业界比较认可的Lisp应用。至于Common Lisp的应用,Paul Graham的Viaweb(后来被Yahoo!收购,成为Yahoo! Store)是个好例子。最著名的估计是,详情可以参考田春冰河的博客
上一篇:[原]时光荏苒
下一篇:[原]重新开始学习Scheme(2):线性递归以及循环不变式

文章评论