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中使用的文章. 这一讲的主要对 ...
随机推荐
- Set<E> 接口简明
java. util. Set 接口 Set 接口中的方法和 Collection 中方法一致的.Set 接口取出方式只有一种, 迭代器 . HashSet : 底层数据结构是哈希表,线程 是不同步的 ...
- java集合详解
1.java集合框架的层次结构 Collection接口: Set接口: HashSet具体类 LinkedHashSet具体类 TreeSet具体类 List接口: ArrayList具体类 L ...
- 原生js代码挑战之动态添加双色球
var ballArr = []; //存放已有的红球,用来排除重复和排序window.onload = function(){ var btn = document.createElement(&q ...
- Java 嵌套类基础详解
目录 1. 什么是嵌套类? 2. 为什么要使用嵌套类? 3. 嵌套类的类型 4. 静态嵌套类 5. 非静态嵌套类 5.1 成员内部类 5.2 局部内部类 5.3 匿名内部类 6. 嵌套接口 1. 什么 ...
- hibernate--hibernate.cfg.xml常用配置详解
在hibernate中最重要的两个配置文件就是hibernate.cfg.xml和xxx.hbm.xml文件,前者是一些配置信息,后者是配置表和对象的映射关系,可以通过注解的方式来取代. 本篇文章主要 ...
- [HAOI2007]分割矩阵
题目描述 将一个a*b的数字矩阵进行如下分割:将原矩阵沿某一条直线分割成两个矩阵,再将生成的两个矩阵继续如此分割(当然也可以只分割其中的一个),这样分割了(n-1)次后,原矩阵被分割成了n个矩阵.(每 ...
- 2-XOR-SAT
[题目描述]SAT(Satisfiability,可满足性)问题是著名的 NP 完全问题,它的内容是:判断由有限个布尔变量及其“非”用“或”操作连接起来的表达式组是否可以都为 TRUE.2-SAT 问 ...
- SAC E#1 - 一道难题 Tree
题目背景 冴月麟和魏潇承是好朋友. 题目描述 冴月麟为了守护幻想乡,而制造了幻想乡的倒影,将真实的幻想乡封印了.任何人都无法进入真实的幻想乡了,但是她给前来救她的魏潇承留了一个线索. 她设置了一棵树( ...
- 配置mysql使其允许外部ip进行登录
这两天在做一个数据库的项目,用到了mysql,需要通过外部的ip远程访问mysql,发现默认的mysql是不允许远程访问的,需要做简单的配置. 如下: 1. 打开一个终端(cmd)输入 mysql - ...
- 《Java技术》的第二次作业
(一)学习总结 1.什么是构造方法?什么是构造方法的重载?下面的程序是否可以通过编译?为什么? (1) 构造方法用于在创建对象时对其进行初始化,且方法名与类名相同,方法名前面没有返回值类型的声明,不能 ...