提交 e1e72e78 编写于 作者: G guenchi

update

上级 a093cf70
......@@ -30,11 +30,19 @@
S表达式的第二个优点,也是最重要的一个,便是这个结构很容易表达为以操作符为节点的树状结构:
比如`(* (+ 1 2) (- 3 4))`这个Scheme程序,它具有一个根节点`*`,根节点的叶子是两个`()`
比如
`(* (+ 1 2) (- 3 4))`这个Scheme程序,它具有一个根节点`*`,根节点的叶子是两个`()`
而这两个括号分别是`+``-`节点,叶子分别是`1 2``3 4`
在计算中,我们必须等待根节点`*`的两个叶子分别得到值,才能进行`*`运算。
```scheme
(*
(+ 1 2)
(- 3 4))
```
在计算中,我们发现必须等待根节点`*`的两个叶子分别得到值,才能进行`*`运算。
如此我们便触及到Scheme程序的另一个核心规律,总是对最尖端的叶子先求值,依次递归,直到最后一个根节点。
......
# 引用
上一章我们叙述了简单的Scheme表达式,它们足够构成复杂的程序了。
然而在LISP的世界这只是开始,在LISP的世界中,我们常常希望去操作程序本身。
比如我们希望创建一个程序,来操纵前文所述程序右子叶子的左右叶子。
```scheme
(* (*
(+ 1 2) -> (+ 1 2)
(- 3 4)) (- 4 3))
```
我们设想一个过程`change`,它的作用需要做到
`(change (* (+ 1 2) (- 3 4)))` -> `(* (+ 1 2) (- 4 3))`
> 在Scheme的世界中,我们通常称呼的函数function一般被称为过程procedure.
先不管我们如何去实现`change`,可能你会发现光使用它就出了问题:
`(change (* (+ 1 2) (- 3 4)))` 会在你变换树状结构之前便优先求值`(+ 1 2)``(- 3 4)`,所以程序的下一步便成了`(change (* 3 -1))`然后变成`(change -3)`,这是无论如何也无法输出`(* (+ 1 2) (- 4 3))`的。
这便是第一个问题,我们需要一种机制,让`(+ 1 2)``(- 3 4)``change`运行之前刹住车。
当我们想得更远一点,会发现麻烦并未止步于此:
也许某天我们不再满足于
```scheme
(* (*
(+ 1 2) -> (+ 1 2)
(- 3 4)) (- 4 3))
```
我们想要这个
```scheme
(* (+
(+ 1 2) -> (* 1 2)
(- 3 4)) (* 4 3))
```
这时我们的`change`不仅需要给第一个操作数刹车,它还需要干第二件出格的事,接受原本是操作符的`+ - *`作为操作数。
因为`change`好歹得这样用:
`(change (* (+ 1 2) (- 3 4)) * +)`
这时我们需要第二个机制,它可以冻结操作数的功能,让它表示它的意义而不执行。
***1. 我们需要保留程序中的一段代码不执行。***
***2. 我们需要指代操作数名字的一面,而不是功能。***
这个复杂的功能完美的统一到一个最简单的结构 *引用* `(quote)`,它界定其中的内容不会被运行。
> 在Scheme中,quote有重要的作用,它代表标志符的符号的一面。而不被quote住的标志符代表它作为程序的一面。LISP与其他程序语言最大的区别和其终极奥义它可以将代码视作数据,也可以将代码视作数据。在这种情况下我们必须明确一个标志符在当下是否被自动进行求值。即它对编译器展现它名字的一面,还是它程序的一面。这个区别便由quote来表示。
`(change (quote (* (+ 1 2) (- 3 4))))` 便能确保优先运行的是`change`
这个符号如此常用,所以Scheme编译器默认给他分配了一个读取器宏`'`
***凡是`'`后跟随的内容,视为被(quote ...)包裹。***
上式便简化为`(change '(* (+ 1 2) (- 3 4)))`
被引用的括号与其中的内容`'(* (+ 1 2) (- 3 4))`也构成了LISP中最常见的数据结构-- 链表。
最基本的链表只有一个括号`'(+ 1 2 3 4 5)`,或许你也想使用纯数据结构`'(1 2 3 4 5)`
同时,我们想要表达操作数名字的那一面时,我们可以这样:`'change '+ '- '* '/`
接下来让我们走的更远:
我们让过程`(change)`在替换叶子的同时对一部分求值:
```scheme
(* (*
(+ 1 2) -> 3
(- 3 4)) (* 4 3))
```
这个时候我们需要使用高级版的quote:quasiquote,它表示接受结构内的部分求值行为。为简便我们在下面的例子中只使用它的读取器宏`` ` ``,它是往右斜的单引号。
同时我们需要`unquote`来解引用,它的读取器宏是逗号`,`
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册