Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
CSDN 技术社区
skill_tree_scheme
提交
8564fdf8
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看板
提交
8564fdf8
编写于
10月 26, 2022
作者:
G
guenchi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add callcc
上级
f70f3d86
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
224 addition
and
0 deletion
+224
-0
data/3.Scheme高阶/1.Scheme高阶/1.Callcc/exercise_01.md
data/3.Scheme高阶/1.Scheme高阶/1.Callcc/exercise_01.md
+215
-0
data/3.Scheme高阶/1.Scheme高阶/config.json
data/3.Scheme高阶/1.Scheme高阶/config.json
+9
-0
未找到文件。
data/3.Scheme高阶/1.Scheme高阶/1.Callcc/exercise_01.md
0 → 100644
浏览文件 @
8564fdf8
call/cc表达式,提取当前位置的延续。
如以下的程序:
```
scheme
(
+
(
*
(
call/cc
(
lambda
(
c
)
(
+
(
c
2
)
3
)))
5
)
8
)
```
可以先简化为
```
scheme
(
+
(
*
(
call/cc
…)
5
)
8
)
```
什么叫当前位置的延续呢?
比如
```
scheme
(
+
(
*
x
5
)
8
)
```
对于x来说,它的延续就是它将要被做的事。这里就是,
*
5然后+8。
这个延续如何用代码表示呢?
```
scheme
(
lambda
(
k
)
(
+
(
*
k
5
)
8
))
```
那么对于x 也就是
`(call/cc …)`
的延续就是
```
scheme
(
lambda
(
k
)
(
+
(
*
k
5
)
8
))
```
现在来看(call/cc ...)语句内部,当call/cc取得当前位置的延续后,它需要一个回调函数来使用这个延续。对吧?因为从这里控制流开始向回调函数处跳转,而不是返回到(call/cc ...)所在的当前栈。
也就是说,
`(+ (* (call/cc …)5) 8)`
的加法和乘法是永远也不会执行的!从call/cc开始,就走了,走了,永远也不回来了。去哪了,去(call/cc f)的回调函数f那里了。
然后来看回调函数f:
```
scheme
(
lambda
(
c
)
(
+
(
c
2
)
3
))
```
f被以call/cc得到的延续为参数调用,同时这个延续也作为f的回调函数,请注意后一点。
参数c在这里带入
```
scheme
(
lambda
(
k
)
(
+
(
*
k
5
)
8
))
```
那么回调函数f在这里的求值就是:
```
scheme
((
lambda
(
c
)
(
+
(
c
2
)
3
))
(
lambda
(
k
)
(
+
(
*
k
5
)
8
)))
```
注意 这里的求值是永远不会被返回的。(普通scheme程序这里会得到21)
因为回调函数f,在求值时将控制流传递给了它的回调函数c,如果使用有return的语言来表达的话。
```
javascript
var
f
=
function
(
c
){
var
x
=
c
(
2
);
return
x
;
x
+
3
;
}
```
x+3是永远不会执行的。
这样的返回方式是call/cc的特殊之处,正是这样,它才能暴露出整个程序的控制流。
所以整个程序的求值返回了
```
scheme
((
lambda
(
c
)
(
c
2
))
(
lambda
(
k
)
(
+
(
*
k
5
)
8
)))
```
的结果。
注意这个结果和
`(+ (* x 5) 8)`
这个外层函数一点关系都没有,它已经成为过去了。
那么现在我们就很好理解
```
scheme
(
set!
*this*
c
)
(
*this*
10
)
```
这样的写法了。延续c只不过被储存了起来,随时调用罢了。而这个c在当下与过去的外层函数一点关系没有了。
```
scheme
(
+
(
*
(
call/cc
(
lambda
(
c
)
(
set!
*this*
c
)
1
))
5
)
8
)
```
在这个例子里,因为回调函数也就是延续c一直没有被调用。
那么call/cc的回调函数会返回1,结果是13。
但这里我们把延续存起来了,于是:
```
scheme
(
*this*
2
)
```
相当于
```
scheme
((
lambda
(
c
)
(
c
2
))
(
lambda
(
k
)
(
+
(
*
k
5
)
8
)))
```
得到 18
```
scheme
(
*this*
3
)
```
相当于
```
scheme
((
lambda
(
c
)
(
c
3
))
(
lambda
(
k
)
(
+
(
*
k
5
)
8
)))
```
得到 23
可以看到这里的
*this*
等于c 和原函数
`(+ (* x 5) 8)`
一点关系没有了。
\ No newline at end of file
data/3.Scheme高阶/1.Scheme高阶/config.json
0 → 100644
浏览文件 @
8564fdf8
{
"node_id"
:
"scheme-2575c2cd26f847ea93415549c6c026a2"
,
"keywords"
:
[],
"keywords_must"
:
[],
"keywords_forbid"
:
[],
"group"
:
0
,
"subtree"
:
""
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录