TSPL学习笔记(2):过程和变量绑定
变量的引用
语法: variable
返回: variable的值
如果在某个范围内存在对某个标识符的变量绑定,那么当这个标识符以表达式的形式出现的时候被认为是其所绑定变量的值.
在引用一个标识符的时候,如果这个标识符没有被绑定为变量,关键字,记录名或其它的实体那么解释器/编译器将会报语法错误.定义(通过define表达式)的有效范围是整个域(例如lambda表达式的整个body),所以只要引用定义的地方没有对定义求值则相关的定义不必出现在它被引用之前.例如:
(define f(lambda (x)(g x)))
(define g(lambda (x)(+ x x)))
g
的定义出现在对它的引用(g x)
之后,但定义f
的时候并不对(g x)
求值所以上述代码是合法的.
而下面的代码则是非法的:
(define q (g 3))
(define g(lambda (x)(+ x x)))
因为在q
的定义中需要对g
求值,而在这个位置上q
的定义还没完成.
Lambda
语法:(lambda formals body1 body2 ...)
返回:一个过程
库:(rnrs base),(rnrs)
lambda语法形式用于创建过程.任何创建过程或建立局部变量绑定的语法形式最终都是通过一系列的lambda或case-lambda语句实现的.
在lambda语句中,出现在formals
中的变量都是过程参数,body1,body2 ...
组成了过程的body.
形参实参绑定:
- 如果
formals
是一个完整的由变量组成的list
,例如:(x y x),则每个变量分别与其对应的实参绑定,实参的数量太多或太少都会引发异常 - 如果
formals
是一个单一的变量,例如:z,则所有实参形成一个list与z绑定. - 如果
formals
不是一个完整的list
,例如:(x y . z),则相应的实参绑定到x,y,其余实参形成一个list与z绑定.如果实参数量太少会引发异常.
当body被求值的时候,body中的表达式会按顺序被求值,而最后一个表达式的求出的值作为过程的返回值被返回.
Case-Lambda
Scheme的lambda不能直接支持不同参数数量的过程定义重载,要实现这个重载定义需要使用case-Lambda
.
语法: (case-lambda clause ...)
返回: 一个过程
库: (rnrs control) , (rnrs)
一个case-lambda表达式由一系列的子句组成,每一条子句都与lambda表达式类似:
[formals body1 body2 ...]
由case-lambda表达式创建的过程被调用的时候,按字句定义的顺序将其formals
与实参匹配,匹配规则与lambda创建的过程一样,第一个被匹配成功的子句会被求值,如果没有一个子句匹配成功会引发异常.
例如下面是一个case-lambda的例子:
(define make-list(case-lambda[(n) (make-list n #f)][(n x)(do ([n n (- n 1)] [ls '() (cons x ls)])((zero? n) ls))]))
局部绑定
语法: (let ((var expr) ...) body1 body2 ...)
返回: 最后一个body表达式的值
库: (rnrs base) , (rnrs)
let表达式建立局部变量绑定,var被绑定为expr求的值,在let表达式的body内可以引用var.let表达式的body由一系列的body 1 body 2 ...
子句组成,其求值计算与lambda一样.
let
与let*
,letrec
,letrec*
的主要区别在于,var在expr的作用域内是不可见的,所以在expr中引用var是非法的.
let
,letrec
和let*
,letrec*
的区别在于,如果有多个(var expr)
,前两者对expr
的求值顺序是不确定的,而后两者严格按照从左到右的顺序对expr
求值.
let
是一种扩展语法其语法定义如下:
(define-syntax let(syntax-rules ()[(_ ((x e) ...) b1 b2 ...)((lambda (x ...) b1 b2 ...) e ...)]))
语法: (let* ((var expr) ...) body1 body2 ...)
返回: 最后一个body表达式的值
库: (rnrs base) , (rnrs)
如上所述,与let唯一的区别在于expr
的求值顺序.
任何的let*
表达式都可以转化为用嵌套的let
表达式实现:
(define-syntax let*(syntax-rules ()[(_ () e1 e2 ...)(let () e1 e2 ...)][(_ ((x1 v1) (x2 v2) ...) e1 e2 ...)(let ((x1 v1))(let* ((x2 v2) ...) e1 e2 ...))]))
语法: (letrec ((var expr) ...) body 1 body 2 ...)
返回: 最后一个body表达式的值
库: (rnrs base) , (rnrs)
letrec
与let
和let*
的唯一区别在于var在expr中是可见的,所以可以在expr中递归的引用var,例如:
(letrec ([sum (lambda (x)(if (zero? x)0(+ x (sum (- x 1)))))])(sum 5)) -> 15
语法: (letrec* ((var expr) ...) body1 body2 ...)
返回: 最后一个body表达式的值
库: (rnrs base) , (rnrs)
与letrec
类似只是expr
的求值顺序严格按照从左往右执行.
多值局部绑定
语法: (let-values ((formals expr) ...) body1 body2 ...)
语法: (let*-values ((formals expr) ...) body1 body2 ...)
返回: 最后一个body表达式的值
库: (rnrs base) , (rnrs)
let-values
和let*-values
可以方便的为formals
中的变量绑定值,例如:
(let-values ([(a b) (values 1 2)] [c (values 1 2 3)])(list a b c)) -> (1 2 (1 2 3))
a被与1绑定,b与2绑定,c与(1 2 3)绑定.
上述代码还可以改成如下等价形式:
(let-values ([(a b c) (values 1 2 (list 1 2 3))])(list a b c))
变量定义
语法: (define var expr)
语法: (define var)
语法: (define (var0 var1 ...) body1 body2 ...)
语法: (define (var0 . varr ) body1 body2 ...)
语法: (define (var0 var1 var2 ... . varr ) body1 body2 ...)
库: (rnrs base) , (rnrs)
第一种语法形式将var与expr绑定,第二种等价于(define var unspecified)
其余的分别等价于:
(define var0(lambda (var1 ...)body1 body2 ...))(define var0(lambda varrbody1 body2 ...))(define var0(lambda (var1 var2 ... . varr)body1 body2 ...))
赋值
语法: (set! var expr)
返回: 未定义
库: (rnrs base) , (rnrs)
转载于:https://www.cnblogs.com/sniperHW/p/3973205.html
TSPL学习笔记(2):过程和变量绑定相关推荐
- 炼数成金Tensorflow学习笔记之2.2_变量
炼数成金Tensorflow学习笔记之2.2_变量 代码及分析 代码及分析 import tensorflow as tfx = tf.Variable([1, 2]) a = tf.constant ...
- SilverLight学习笔记--建立Silverlight自定义控件(5)--绑定动画效果
有了上述的基础,我们进一步完善我们的自定义控件,在此我们将创建Storyboard和前面的添加事件处理方法为我们的自定义控件加上动画效果. 1.首先,在MyDesignButton项目中进一步完善 ...
- JavaScript学习笔记——JS中的变量复制、参数传递和作用域链
今天在看书的过程中,又发现了自己目前对Javascript存在的一个知识模糊点:JS的作用域链,所以就通过查资料看书对作用域链相关的内容进行了学习.今天学习笔记主要有这样几个关键字:变量.参数传递.执 ...
- C语言学习笔记08-函数、变量作用域{}
C语言自定义函数 函数 / 方法(面向对象语言),将功能重复的代码段(原始的方式是cv)提取抽象出main方法外,将其放入一个新的函数中,从而在main中只需要调用该函数就可完成一项复杂的工作,代码会 ...
- Java 虚拟机学习笔记 | 类加载过程和对象的创建流程
前言 创建对象是 Java 语言绕不开的话题,那么对象是如何创建出来的呢?我们今天就来聊一聊.对象创建第一步就是检查类是否加载,而类的加载又牵扯到类的加载过程.如果单说对象的创建而绕开类的加载过程,感 ...
- C#.NET学习笔记7--11---算术运算符,变量赋值,变量的交换,布尔表达式1,布尔表达式2
C#.NET学习笔记7---算术运算符 2013/9/6 技术qq交流群:JavaDream:251572072 教程下载,在线交流:创梦IT社区:___________以前的网站现在不弄了,抱歉 ...
- shell脚本编程学习笔记2(xdl)——Bash变量
shell脚本编程学习笔记2--Bash变量 1,变量简介 1,计算机内存单元2,设置规则字母数组下划线组成,不能以数字开头Bash中,默认类型字符串型,变量类型可修改 2,Bash变量规则 1,变量 ...
- Vue学习笔记(六) 表单输入绑定
v-model 指令在表单元素上创建双向数据绑定,它负责用于监听用户输入事件以更新数据 注意,v-model 会忽略所有表单元素特性的初始值,而总是将 Vue 实例的数据作为数据来源 1.输入框 &l ...
- go 学习笔记之有意思的变量和不安分的常量
首先希望学习 Go 语言的爱好者至少拥有其他语言的编程经验,如果是完全零基础的小白用户,本教程可能并不适合阅读或尝试阅读看看,系列笔记的目标是站在其他语言的角度学习新的语言,理解 Go 语言,进而写出 ...
- TSPL学习笔记(1)
扩展语法(Syntactic extensions) 扩展语法就是通过核心语法或已经定义的扩展语法创建一种新的语法模式. Scheme核心语法模式包括: 顶层定义 常量 变量 过程应用 '(quote ...
最新文章
- Linux Linux程序练习十一(网络编程大文件发送UDP版)
- Pycharm ipynb
- 《JAVA与模式》之工厂方法模式
- 查看docker镜像的dockerfile脚本json信息
- jquery --- 使用when方法等待2个异步事件结束后执行某一个函数.
- 如何建立自己的知识体系?(摘)
- python显示日历_python显示日期
- php中图片怎么加样式,html5实现各种图片样式实例用法汇总
- 在eclipse4.5.1官方英文版利用官方语言包汉化的方法
- android开发实现选择列表,Android使用RecyclerView实现列表数据选择操作
- Centos7搭建openV pn服务器
- CNKI文献pdf批量下载
- STM32 下载调试口(JTAG+SWD)禁用及作为普通IO口
- 【知识图谱】OpenKG 发布多个新冠病毒相关开放知识图谱
- xp系统怎么关闭wmi服务器,教你win10系统wmi服务器怎么关闭
- 切换linux默认桌面,Debian默认桌面再次切换到Gnome
- 智能手机成瘾者的大脑功能和结构的改变
- 抽象类和抽象方法_30酷抽象和背景Photoshop教程
- TD-SCDMA与TD-LTE异构网络垂直切换算法
- pytorch 移植到Android平台(一)
热门文章
- python流星雨代码_用python一起来看流星雨
- oracle的存储过程怎么运行时间,ORACLE 定时运行存储过程经常使用时间间隔
- c# zxing条形码设置密度_C# 中 ZXing.Net 怎样突破 条形码 多识别 数量限制
- netty 使用阻塞发送_「解」互联网大厂Java面试题——Netty 面试题解析
- linux 格式化ntfs u盘,手机u盘数据恢复linux格式化为ntfs格式
- java 中的radix_线程“main”中的异常java.lang.NumberFormatException:Radix超出范围
- python表格数据过滤复制到另外一个表格
- 华为模拟器ensp与真实机器连接使用的配置内容一
- 查询SQL最近一次启动时间
- docker给php装swoole,制作php+swoole的Docker环境