Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
CSDN 技术社区
skill_tree_scheme
提交
e1e72e78
skill_tree_scheme
项目概览
CSDN 技术社区
/
skill_tree_scheme
通知
1
Star
2
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
skill_tree_scheme
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
e1e72e78
编写于
11月 09, 2022
作者:
G
guenchi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update
上级
a093cf70
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
99 addition
and
2 deletion
+99
-2
data/1.Scheme初阶/1.Scheme入门/2.S表达式/exercise_02.md
data/1.Scheme初阶/1.Scheme入门/2.S表达式/exercise_02.md
+10
-2
data/1.Scheme初阶/1.Scheme入门/3.引用quote/exercise_03.md
data/1.Scheme初阶/1.Scheme入门/3.引用quote/exercise_03.md
+89
-0
data/1.Scheme初阶/1.Scheme入门/3.引用符quote/exercise_03.md
data/1.Scheme初阶/1.Scheme入门/3.引用符quote/exercise_03.md
+0
-0
未找到文件。
data/1.Scheme初阶/1.Scheme入门/2.S表达式/exercise_02.md
浏览文件 @
e1e72e78
...
@@ -30,11 +30,19 @@
...
@@ -30,11 +30,19 @@
S表达式的第二个优点,也是最重要的一个,便是这个结构很容易表达为以操作符为节点的树状结构:
S表达式的第二个优点,也是最重要的一个,便是这个结构很容易表达为以操作符为节点的树状结构:
比如
`(* (+ 1 2) (- 3 4))`
这个Scheme程序,它具有一个根节点
`*`
,根节点的叶子是两个
`()`
。
比如
`(* (+ 1 2) (- 3 4))`
这个Scheme程序,它具有一个根节点
`*`
,根节点的叶子是两个
`()`
。
而这两个括号分别是
`+`
和
`-`
节点,叶子分别是
`1 2`
和
`3 4`
。
而这两个括号分别是
`+`
和
`-`
节点,叶子分别是
`1 2`
和
`3 4`
。
在计算中,我们必须等待根节点
`*`
的两个叶子分别得到值,才能进行
`*`
运算。
```
scheme
(
*
(
+
1
2
)
(
-
3
4
))
```
在计算中,我们发现必须等待根节点
`*`
的两个叶子分别得到值,才能进行
`*`
运算。
如此我们便触及到Scheme程序的另一个核心规律,总是对最尖端的叶子先求值,依次递归,直到最后一个根节点。
如此我们便触及到Scheme程序的另一个核心规律,总是对最尖端的叶子先求值,依次递归,直到最后一个根节点。
...
...
data/1.Scheme初阶/1.Scheme入门/3.引用quote/exercise_03.md
0 → 100644
浏览文件 @
e1e72e78
# 引用
上一章我们叙述了简单的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
data/1.Scheme初阶/1.Scheme入门/3.引用符quote/exercise_03.md
已删除
100644 → 0
浏览文件 @
a093cf70
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录