跟踪lambda表达式评估

时间:2013-02-15 22:16:12

标签: lambda scheme sicp operator-precedence interpreted-language

我在使用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)))))

和任务:

  

直接定义onetwo(不是zeroadd-1)。

我希望根据评估onetwo的结果来检查我对(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)))
>

2 个答案:

答案 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)))

现在很清楚fx的含义是什么:x代表“零”数据元素的具体实现,f代表“后继”操作的具体实现,与“零”的给定具体实现兼容。 fx应该真正以名字命名:

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. 评估组合的子表达式。
    2. 将作为最左侧子表达式(运算符)的值的过程应用于作为其他子表达式(操作数)的值的参数。

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}

然后根据sz的实际定义进行计算。这就是上面显示的等式(1)表示的更短的符号。