我在使用Scheme中的一些看似棘手的lambda表达式时遇到了麻烦,我想看看它们是如何被解释器评估的。
我希望Scheme解释器打印所有评估步骤,如SICP Section 1.1.5, "The Substitution Model for Procedure Application"中所示。
我正在寻找使用任何Scheme解释器的解决方案。我已经尝试了Racket's tracing,但它只跟踪过程调用,而不是每个表达式。
激励示例
鉴于来自SICP Exercise 2.6的教会数字的定义:
(define zero (lambda (f) (lambda (x) x)))
(define (add-1 n)
(lambda (f) (lambda (x) (f ((n f) x)))))
和任务:
直接定义
one
和two
(不是zero
和add-1
)。
我希望根据评估one
和two
的结果来检查我对(add-1 zero)
和(add-1 (add-1 zero))
的定义。
这就是我希望Scheme解释器打印出来的内容:
> (add-1 zero)
(add-1 (lambda (f) (lambda (x) x)))
(lambda (f) (lambda (x) (f (((lambda (f) (lambda (x) x)) f) x))))
(lambda (f) (lambda (x) (f ((lambda (x) x) x))))
(lambda (f) (lambda (x) (f x)))
>
答案 0 :(得分:2)
尝试使用Racket的内置步进器,这个answer中有一些方法。
答案 1 :(得分:1)
使用类似组合器的方程(was once called applicative style I believe)
非常容易zero f x = x
add1 n f x = f (n f x)
one f x = add1 zero f x = f (zero f x) = f x **(1)**
two f x = add1 one f x = f (one f x) = f (f x) **(2)**
使用组合器,一切都是咖喱的:a b c d
实际上是(((a b) c) d)
而a b c = d
相当于(define a (lambda (b) (lambda (c) d)))
。
现在很清楚f
和x
的含义是什么:x
代表“零”数据元素的具体实现,f
代表“后继”操作的具体实现,与“零”的给定具体实现兼容。 f
和x
应该真正以名字命名:
zero s z = z
add1 n s z = s (n s z)
不再那么狡猾了,语法更方便,对吧?无论如何,lambda
本身就是一个印刷事故。现在,
one s z = s z ; e.g. (1+ 0)
two s z = s (s z) ; e.g. (1+ (1+ 0))
根据SICP 1.1.3 combinations evaluation程序
跟踪步骤和1.1.5 sustitution model for procedure application
我们得到了
add1 zero =
( n f x => f (n f x) ) ( f x => x ) =
( f x => f ( ( f x => x ) f x ) )
这里替换实际上停止了,因为结果是一个简单的lambda表达式,即不是组合。只有当提供了两个以上的参数时,评估才会完整:
add1 zero s z =
( n f x => f (n f x) ) ( f x => x ) s z =
( f x => f ( ( f x => x ) f x ) ) s z =
( x => {s} ( ( f x => x ) {s} x ) ) z = ; {s} is definition-of s
{s} ( ( f x => x ) {s} {z} ) = ; {z} is definition-of z
; must find the value of the operand in combination
{s} ( ( x => x ) {z} ) =
{s} {z}
然后根据s
和z
的实际定义进行计算。这就是上面显示的等式(1)表示的更短的符号。