Scheme r5rs letrec的用法
说明,这是r5rs的用法.
(letrec ((<variable> <init>) ...) <body>)
假设((<variable> <init>) ...)是变量定义块V,<body>是执行块B.
letrec最常见的用法就是用于绑定函数对象,让V里面定义的所有变量可以在运行时相互引用,不受位置前后的限制.比如:
> (letrec ((x (lambda () (+ y y)))
(y ))
(+ (x) y))
这说明运行(+ (x) y)时,函数对象x可以读取y对象的值,尽管y在x之后才绑定的. 这一点letrec很像顶层的运作模式:
> (define x (lambda () (+ y y)))
> (define y )
> (+ (x) y)
只不过letrec创建的是一个本地作用域,而且语法上更简单.
将letrec替换为let*或let将出错:
> (let* ((x (lambda () (+ y y)))
(y ))
(+ (x) y))
. . y: undefined;
cannot reference an identifier before its definition
> (let ((x (lambda () (+ y y)))
(y ))
(+ (x) y))
. . y: undefined;
cannot reference an identifier before its definition
>
let*最多只能让靠后的variable引用靠前的variable.交换一下x,y的定义位置,就正常了:
> (let* ((y )
(x (lambda () (+ y y))))
(+ (x) y))
而let限制更严格,各variable只能在body中被引用:
> (let ((y )
(x (lambda () (+ y y))))
(+ (x) y))
. . y: undefined;
cannot reference an identifier before its definition
当你表达式里含有一些相互递归的函数时,letrec非常合适.例如下面这个判断奇偶数的函数:
> (letrec ((ieven?
(lambda (n)
(if (zero? n)
#t
(iodd? (- n )))))
(iodd?
(lambda (n)
(if (zero? n)
#f
(ieven? (- n ))))))
(ieven? ))
#f
看起来letrec很强大的样子,那么,letrec的限制是什么呢?(准确说是r5rs的限制.Racket不存在这种限制)
letrec要求<init>必须能够独立成值,否则letrec绑定就会出问题.以下摘自r5rs:
One restriction on letrec is very important: it must be possible to evaluate each <init> without assigning or referring to the value of any <variable>.In the most common uses of letrec, all the <init>s are lambda expressions and the restriction is satisfied automatically.
比如下面这个,b绑定不了2:
> (letrec ((a )(b a)) b)
#<undefined>
对比顶层运作,不存在这种限制:
> (define a )
> (define b a)
> b
那为什么lambda表达式能够自动地满足这个要求呢?
因为一个lambda表达式是一个函数对象,它本身就是一个值.相当于100这种整数对象.
Scheme不会在定义时严格检查lambda.比如里面的某变量是否已绑定对象,lambda被执行时才知道会不会出问题.
> (lambda (n)(xxx? (- n 1)))
#<procedure>
> ((lambda (n)(xxx? (- n 1))) 3)
. . xxx?: undefined;
cannot reference undefined identifier
>
那let*存在的意义是什么? 看这种情况:
> (letrec ((a 2)(b a)) b)
#<undefined>
> (let* ((a 2)(b a)) b)
2
>
let*能让(b a)读取前面的定义(a 2),从而让b等于2.letrec就不行.
而let对比let*限制更多,因此性能应该是更好的.在let和let*都能正常运行的时候,显然应该选择let.
这应该就是let,let*和letrec各自存在的意义吧.
注:方言Racket的letrec没有此限制.
> (letrec ((a )(b a)) b)
Scheme r5rs letrec的用法的更多相关文章
- call/cc 总结 | Scheme
call/cc 总结 | Scheme 来源 https://www.sczyh30.com/posts/Functional-Programming/call-with-current-contin ...
- 算法语言Scheme修订6报告 R6RS简体中文翻译
算法语言Scheme修订6报告 R6RS简体中文翻译 来源 https://r6rs.mrliu.org/ MICHAEL SPERBERR. KENT DYBVIG, MATTHEW FLATT ...
- let区别(关于racket和r5rs)
R5RS is the Revised5 Report on the Algorithmic Language Scheme.参考http://www.schemers.org/Documents/S ...
- scheme 教程 #lang racket
scheme 教程 #lang racket 来源 https://blog.csdn.net/yemeishenme/article/details/51471037 原文: https://le ...
- 开始学习Scheme
开始学习Scheme 函数式编程(Functional Programming)是在MIT研究人工智能(Artificial Intelligence)时发明的,其编程语言为Lisp.确切地说,L ...
- Android基础学习第三篇—Intent的用法
写在前面的话: 1. 最近在自学Android,也是边看书边写一些Demo,由于知识点越来越多,脑子越来越记不清楚,所以打算写成读书笔记,供以后查看,也算是把自己学到所理解的东西写出来,献丑,如有不对 ...
- awk 的一些用法
awk,我觉得是Linux里面处理文本最精妙的命令,它是一个行处理的命令,它最初级的用法是:给定一些简单的pattern,然后按照这个pattern 去搜索匹配的行.它的高级用法是用awk来编程,除了 ...
- Android网页中tel,sms,mailTo,Intent,Market协议用法总结
tel:协议---拨打电话 <a href="tel:">调出拨号界面</a> <a href="tel:10086">调 ...
- 【Win10 UWP】URI Scheme(一):Windows Store协议的解析和使用
协议是Windows Phone和Windows Store应用的一个重要特点,可以做到在不同应用之间进行互相呼起调用.小小协议,学问大着呢.我打算写几篇关于协议在UWP中使用的文章. 这一讲的主要对 ...
随机推荐
- 利用JS去做响应式布局
利用JS去做响应式布局 js动态改变布局方式 // 取浏览器可视区高宽 var lw = $(window).width(); var lh = $(window).height();// 页面加载完 ...
- C# 传统四舍五入保留两位小数(网上流传好多错误的版本)
关于C#里面的Math.Round,很多人都会用到,而且以为是四舍五入,其实不是这样的: C#里面的Math.Round是符合IEEE标准的“四舍五入”,其实是五舍六入. 网上好多流传的下面这种方式实 ...
- Python默认版本切换
Mac上自带python2.7 版本,但是我又下了一个3.7版本(下载的版本默认安装在 /Library/Frameworks/Python.framework/Versions/3.7/bin/py ...
- [HNOI2014]江南乐
Description 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一 ...
- [HNOI2012]射箭
Description 沫沫最近在玩一个二维的射箭游戏,如下图 1 所示,这个游戏中的 x 轴在地面,第一象限中有一些竖直线段作为靶子,任意两个靶子都没有公共部分,也不会接触坐标轴.沫沫控制一个位于( ...
- NOIP 2009 最优贸易
题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路 ...
- hihocoder 1388 fft循环矩阵
#1388 : Periodic Signal 时间限制:5000ms 单点时限:5000ms 内存限制:256MB 描述 Profess X is an expert in signal proce ...
- 【BZOJ1483】【HNOI2009】梦幻布丁
题意:n个连续的点,有若干种颜色,每个颜色会因为某些操作变为另一种颜色,动态查询颜色段数. 解题思路:对每个颜色开一棵平衡树启发式合并应该是最裸的想法,但是我们有更优的! 考虑对每个颜色利用链表储存它 ...
- hdu 5700区间交(线段树)
区间交 Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...
- hdu 1255 覆盖的面积(求覆盖至少两次以上的面积)
了校赛,还有什么途径可以申请加入ACM校队? 覆盖的面积 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K ...