Scheme自学教程 2

来源:互联网 发布:mac口红dareyou试色 编辑:程序博客网 时间:2024/06/11 06:28
导读:
  由 stelee 于 周日, 11/18/2007 - 09:06 提交。programming
  Scheme自学教程 2
  第三章 代码块(Forms)
  读者也许注意到了,在前面那些Scheme的例子中列举了如此多的S表达式,其中隐藏的事实是:程序就是数据。因此,#/c就是一个程序,或者我们可以称为代码块(Forms)。以后,我们会使用更加正式的词汇form来代替程序片段这个说法。scheme执行form #/c从而得到一个值#/c,因为#/c是可以自我求值的。并不是所有的S表达式都是可以自我求值的,比如说,对于symbol的s表达式 xyz来说,其求值的是xyz本省或代表的变量。而列表s表达式(string->number "16")求值结果是数字16。
  并不是所有的s表达是都是有效的程序。如果你写如下的代码(1 . 2),则不会通过编译。Scheme运行一个列表样式的form,首先检查第一个元素,或者说检查head,如果head被执行为一个过程(procedure),那么剩下的则被认为是head元素的参数。这个过程就被应用(apply)于这些参数上
  如果form的head是一个特殊的form,就会以一种特殊的方式来处理,这样的特殊的form,我们见过的包括begin,define和set!,begin就意味着它的子form按顺序执行,整个form的返回值就是最后一个子form的返回值,define定义并给一个变量赋值,set!改变变量绑定的值。
  译者废话:这段话翻译的真的是很费劲,你看懂了吗?我是大概理解了,如果不理解的话,欢迎与我联系
  3.1 过程
  We have seen quite a few primitive Scheme procedures,
  eg, cons, string->list, and the like. Users
  can create their own procedures using the special form
  lambda. For example, the following defines a
  procedure that adds 2to its argument:
  我们已经看到了好多Scheme内置的过程,包括cons,string->list等等。其实用户还可以通过著名的标志性的语句lambda自己来定义过程。比如说,下面这个例子就定义了一个自动 加2的过程:
  (lambda (x) (+ x 2))
  The first subform, (x), is the list of parameters.
  The remaining subform(s) constitute the procedure's
  body. This procedure can be called on an argument,
  just like a primitive procedure:
  第一个子语句 (x),定义了过程的参数。剩下的所有的子语句就是过程体了,定义完毕后,这个过程就可以像内置的过程那样被使用了。
  ((lambda (x) (+ x 2)) 5)
  =>7
  当然,当然,如果我们要多次调用这个函数的话,不用这么麻烦的,记住:函数是第一公民,和整数,字符串一样,所以我们可以用一个变量来代表这个函数。
  (define add2
  (lambda (x) (+ x 2)))
  从此以后事情就变得简单了:
  (add2 4) =>6
  (add2 9) =>11
  3.1.1 过程参数
  lambda-过程的参数是在它的第一个子form中被定义的(就是符号lambda之后的第一个form),add2是一个只有一个参数——官方的说法叫做一元参数——的过程。所以他的参数列表是只有一个元素的列表 (x)还记得列表吗?这和我们熟悉的命令式语言基本一样,有一点,所有的变量x都是局部的。
  同样我们可以定义两元或者多元参数的过程:
  (define area
  (lambda (length breadth)
  (* length breadth)))
  注意,这里我们其实可以有一个更加投机取巧的办法:
  (define area *)
  3.1.2 变参
  学过JavaScript的,PHP的或者Python的同学一定对可变参数很熟悉了。学过Java或者C#的同学,我们很同情你们必学写很多重载来模拟这个过程。为了实现这一点。参数列表必学使用一个特殊的符号来标记(又是特殊符号,不过相对很多语言来说,Scheme里面的特殊符号或者所谓的语法糖已经很少了)这个特殊的符号就代表着将要被调用的参数。
  一般来说,我们用(x ...)来表示变参。一个符号,或者说一个点对类型的form (x ... . z),在点对类型点前面的那部分在过程调用的时候与调用的参数进行匹配。点后面的变量,则把剩下的参数作为一个list存下来
  说实话,这段话我也不太理解,主要是没有例子,附上原文,大家参考
  In general, the lambdaparameter list can be a list
  of the form (x ...), a symbol, or a dotted pair of
  the form (x ... . z). In the dotted-pair case, all
  the variables before the dot are bound to the
  corresponding arguments in the procedure call, with the
  single variable after the dot picking up all the
  remaining arguments as one list.
  3.2应用(apply)
  Scheme通过使用过程 apply 来调用一个过程(第一个参数),并把这个过程应用到第二个参数的列表元素上(其实就是把第二个参数列表元素作为第一个参数过程的参数)
  (define x '(1 2 3))
  (apply + x)
  =>6
  一般来说,apply后面跟一个参数作为所要调用的过程,在后面跟着数量不一的所要使用的其他参数。而最后一个必须是一个列表。其构造方法就是先应用过程和最后一个参数,计算出结果,然后结合其他的参数作为这个过程调用的新的参数。
  (apply + 1 2 3 x)
  =>12
  我理解其背后的机制应该是: (+ 1 2 3 (+ 1 2 3))
  3.3 顺序
  We used the beginspecial form to bunch together a
  group of subforms that need to be evaluated in
  sequence. Many Scheme forms have implicit
  begins. For example, let's define a 3-argument procedure that
  displays its three arguments, with spaces between
  them. A possible definition is:
  我们可以通过begin这个特殊的form来组织一系列的子form从而让他们可以按照一定的顺序来执行。许多Scheme的form都要求必须以begin来开始,比如如果我们要定义一个过程,按顺序
  (define display3
  (lambda (arg1 arg2 arg3)
  (begin
  (display arg1)
  (display " ")
  (display arg2)
  (display " ")
  (display arg3)
  (newline)))
  在Scheme中,lambda的函数中默认使用begins,所以在我们下面定义的display3中间并不需要显示的使用begin,当然使用了也没有什么坏处,不用只会让事情更简单。
  (define display3
  (lambda (arg1 arg2 arg3)
  (display arg1)
  (display " ")
  (display arg2)
  (display " ")
  (display arg3)
  (newline)))
  >>
  要发表评论,请先登录

本文转自
http://www.leesoft.com.cn/node/7