• (译)Scheme简明教程5Forms代码结构


    第三章 Forms代码结构

    读者们会发现迄今为止我们提供的Scheme示例程序也都是s-表达式。这对所有的Scheme程序来说都适用:程序是数据。

    因此,字符数据#\c也是一个程序,或一个代码结构。我们将使用更通用的说法代码结构而不是程序,这样我们也可以处理程序片段。

    Scheme计算代码结构#\c得到结果#\c,因为#\c可以自运算。但不是所有的s-表达式都可以自运算。比如symbol 表达式 xyz运算得到的结果是xyz这个变量所承载的值;list 表达式 (string->number "16")运算的结果是数字16(注:之前学过的list类型的数据都是类似(1 2 3 4 5)这样,所以称(string->number "16")为列表s-表达式)

    也不是所有的s-表达式都是有效的程序。如果你直接输入点值对(1 . 2),你将会得到一个错误。

    Scheme运行一个列表形式的代码结构时,首先要检测列表第一个元素,或列表头。如果这个列表头是一个过程,则代码结构的其余部分则被当成将传递给这个过程的参数集,而这个过程将接收这些参数并运算。

    如果这个代码结构的列表头是一个特殊的代码结构,则将会采用一种特殊的方式来运行。我们已经碰到过的特殊的代码结构有begin define set!Begin可以让它的子结构可以有序的运算,而最后一个子结构的结果将成为整个代码结构的运行结果。define会声明并会初始化一个变量。set! 可以给已经存在的变量重新赋值。

    3.1          Procedures(过程)

    我们已经见过了许多系统过程,比如,cons string->list等。用户可以使用代码结构lambda来创建自定义的过程。例如,下面定义了一个过程可以在它的参数上加上2

    (lambda (x) (+ x 2))

    第一个子结构,(x)是参数列表。其余的子结构则构成了这个过程执行体。这个过程可以像系统过程一样,通过传递一个参数完成调用:

    ((lambda (x) (+ x 2)) 5)
    =>  7

    如果我们希望能够多次调用这个相同的过程,我们可以每次使用lambda重新创建一个复制品,但我们有更好的方式。我们可以使用一个变量来承载这个过程:

    (define add2
      (lambda (x) (+ x 2)))

    只要需要,我们就可以反复使用add2为参数加上2

    (add2 4) =>  6
    (add2 9) =>  11

    (译者注:定义过程还可以有另一种简单的方式,直接用define而不使用lambda来创建:

    (define (add2 x)

           (+ x 2))

    )

    3.1.1     过程的参数

    lambda 过程的参数由它的第一个子结构(紧跟着lambda标记的那个结构)来定义。add2是一个单参数或一元过程,所以它的参数列表是只有一个元素的列表(x)。标记x作为一个承载过程参数的变量而存在。在过程体中出现的所有x都是指代这个过程的参数。对这个过程体来说x是一个局部变量。

    我们可以为两个参数的过程提供两个元素的列表做参数,通常都是为n个参数的过程提供n个元素的列表。下面是一个可以计算矩形面积的双参数过程。它的两个参数分别是矩形的长和宽。

    (define area
      (lambda (length breadth)
        (* length breadth)))

    我们看到area将它的参数进行相乘,系统过程*也可以实现相乘。我们可以简单的这样做:

    (define area *)
     

    3.1.2     可变数量的参数(不定长参数)

    有一些过程可以在不同的时候传给它不同个数的参数来完成调用。为了实现这样的过程,lambda表达式列表形式的参数要被替换成单个的符号。这个符号会像一个变量一样来承载过程调用时接收到的参数列表。

    通常,lambda的参数列表可以是一个列表构结(x ),一个符号,或者(x . z)这样的一个点值对结构。当参数是一个点值对结构时,在点之前的所有变量将一一对应过程调用时的前几个参数,点之后的那个变量会将剩余的参数值作为一个列表来承载。

    (译者注:以下是几种可变参数的写法:

    ((lambda (x y z)

             (begin

                (display x)

                (newline)

                (display y)

                (newline)

                (display z)

                (newline) ) )

                1 2 3)

    (define (t x y z)

                 (begin

                    (display x)

                    (newline)

                    (display y)

                    (newline)

                    (display z)

                    (newline) ) )

    (t 1 2 3)等价;

    ((lambda x

             (begin

                (display x) ) )

                1 2 3 4)

    (define (t . x)

            (begin

               (display x) ) )

    (t 1 2 3 4)等价;

    ((lambda (x . y)

             (begin

                (display x)

                (newline)

                (display y)

                (newline) ) )

                1 2 3 4 5)

    (define (t x . y)

            (begin

               (display x)

               (newline)

               (display y)

               (newline) ) )

    (t 1 2 3 4 5)等价。

    3.2          Apply过程

    apply过程允许我们直接传递一个装有参数的list 给一个过程来完成对这个过程的批量操作。

    (define x '(1 2 3))
     
    (apply + x)
    =>  6

    通常,apply需要传递一个过程给它,后面紧接着是不定长参数,但最后一个参数值一定要是list。它会根据最后一个参数和中间其它的参数来构建参数列表。然后返回根据这个参数列表来调用过程得到的结果。例如,

    (apply + 1 2 3 x)
    =>  12

    3.3          有序执行

    我们使用begin这个特殊的结构来对一组需要有序执行的子结构来进行打包。许多Scheme的代码结构都隐含了begins。例如,我们定义一个三个参数的过程来输出它们,并用空格间格。一种正确的定义是:

    (define display3
      (lambda (arg1 arg2 arg3)
        (begin
          (display arg1)
          (display " ")
          (display arg2)
          (display " ")
          (display arg3)
          (newline))))

    Scheme中,lambda的语句体都是隐式的begin代码结构。因此,display3语句体中的begin不是必须的,不写时也不会有什么影响。display3更简化的写法是:

    (define display3
      (lambda (arg1 arg2 arg3)
        (display arg1)
        (display " ")
        (display arg2)
        (display " ")
        (display arg3)
        (newline)))
  • 相关阅读:
    sublime c/c++ 环境
    sublime编写markdownm
    第八次课程作业
    第七次课程作业
    第六次作业
    第五次课程作业
    Arithmatic项目修改总结
    第四次课程作业
    第三次课程作业
    课程作业二
  • 原文地址:https://www.cnblogs.com/heros/p/1616417.html
Copyright © 2020-2023  润新知