The R2
about R2
这个toy完全是参照垠神这篇文章做的Java版翻译, 具体内容可以看垠神的文章, 下面是toy的一些细节和自己的总结
the basic match
(a b)
–pattern–>a
b
–spilt–>E1: a E2: b
(a (a b))
–pattern–>a
(a b)
–spilt–>E1: a E2: (a b)
((a b) b)
–pattern–>(a b)
b
–spilt–>E1: (a b) E2: b
((a b) (a b))
–pattern–>(a b)
(a b)
–spilt–>E1: (a b) E2: (a b)
basic syntax and meaning
- 数字:
1
- 变量:
x
- 函数:
(lambda (x) e)
//执行e, 其中x是形参 - 绑定:
(let ([x e1]) e2)
//执行e2, 而e2中x的值为e1, 常用与函数绑定 - 调用:
(e1 e2)
//e1是函数符号, e2是函数入参 - 算术:
(@ e1 e2)
//算式表达式
about env
the explain of env
在这个R2的解释器中, 环境的作用是保存所有出现过的变量所对应的值, 即所谓的变量作用域.
而文章中出现了两种不同的变量作用域, 分别是lexial scoping和dynamic scoping. 这两者最主要的区别静态和动态的区别. 如下例子:
(let ([x 2])
(let ([f (lambda (y) (* x y))])
(let ([x 4])
(f 3))))
;; => 12//dynamic scoping的结果
对于dynamic scoping, 由于变量的值是动态赋值的, 不存在前一个对x的赋值会影响到后一个对x的赋值, 也就是每次都是取变量x最新的值
(let ([x 2])
(let ([f (lambda (y) (* x y))])
(let ([x 4])
(f 3))))
;; => 6//lexical scoping的结果
对于lexical scoping, 变量x的值需要返回到定义这个变量的“环境”中取, 而这个特定的“环境”是在函数创建时确定的.
原因是函数只能“看到”创建时所对应的环境, 而创建后的环境是不在函数的范围内的. 所以, 取变量x的值需要返回函数“看到的环境”中取.
problems
但这里有两个问题, 一个是环境并存问题, 另一个是环境嵌套问题
考虑以下表达式
(+
(let ([x 2]) (let ([f, (lambda (y) (+ x y))]) (f 4))),
(let ([x 2]) (let ([f, (lambda (y) (* x y))]) (f 2))))
简单分析上述表达式, 可知有两个并存的环境, 如下图所示:
考虑以下表达式
(let ([x (let ([x 2])
(let ([f, (lambda (y) (+ x y))])
(f 3)))])
(let ([f (lambda (y) (* x y))])
(f 3)))
上述表达式是存在嵌套的环境的, 如下图所示:
由于对lisp和闭包不熟悉, 所以也没有看出环境是否有实现上述两种结构, 而垠神的文章并没有给出相关的示例, 所以也不知道是否需要实现这种形式, 因此这两种形式的表达式都是无法解释的
目前的代码只能解释最简单和普通的情况, 也就是只有一个特定的“环境”, 如下所示
(let ([x 2]) (let ([f, (lambda (y) (+ x y))]) (f 4))