4.1.5 数据作为程序

4.1.5 数据作为程序
在想一个lisp程序评估lisp表达式,一个类比可能是有帮助的。从一个程序的含义的操作层面的视角,
一个程序是一个抽象的机器的描述。例如,考虑一个相似的计算斐波那些数的程序:

(define (facorial n)
   (if (= n 1) 1 (* (factorial (- n 1)) n))
)

我们可能认为这个程序是一个机器的描述。这个机器包括减法,乘法,和相等性的测试,以及两个位置的
交换器,和其它的斐波那些数的机器。(斐波那些数的机器是无限的,因为它包括其它的斐波那些数的机器)
图4.2是一个关于斐波那些数的机器的流图,显示了这些部分如何用电线连接的。


图4.2 斐波那些数的程序,被表示为一个抽象的机器

在一种相似的方式,我们能认为一个解释器是一个非常特殊的机器,它的输入是一个机器的描述,
给定这个输入,评估器配置它本身,来评估机器的描述。例如,我们喂给我们的评估器一个斐波那些数的定义,
如图4.3,评估器能计算斐波那些数。

图4.3 解释器仿真一个斐波那些数的机器

从这个视图来看,我们的评估器是一个通用的机器。
当这些程序被描述成Lisp程序时,解释器就模拟成
其它的机器了.这是引人注目的事.为了电路,竭力
地想象一个与之类似的解释器.这有一个电路,它的
输入信号是对其它的一些电路的计划的编码,例如
一个过滤器.给定这个输入,电路解释器的行为表现
是像一个有相同的描述的过滤器.这样的通用的电路
几乎是不可想象的复杂.非常好的是一个程序的解释器
是一个相当简单的程序.

解释器的另一个重要方面是它的行为像是被我们的语言
操纵的数据对象与编程语言本身的桥梁.想象一下解释器
程序(被lisp语言实现的)在运行,一个用户输入了一个
表达式给解释器,并且注意了结果。从用户的角度上看,
一个输入的表达式例如(* x x)是编程语言中的一个表达式,
解释器应该执行它。然而从解释器的角度上看,表达式仅是
一个列表(在这个例子中是三个符号的列表 *,x和x)根据
定义好的规则集合,它能被操纵。

用户的程序是解释器的数据,这不需要成为混乱的源头。
在事实上,忽略这种区别,有时是方便的,以程序中使用eval,
给用户显式的解释一个数据对象为一个lisp表达式的能力。
许多lisp方言提供了一个原生的eval程序,程序以一个表
达式为参数,以一个环境为参数,在环境中解释表达式。因此,

(eval '(* 5 5) user-initial-environment)

(eval (cons '* (list 5 5)) user-initial-environment)
将都返回25。

练习4.15
给定一个程序p,它有一个实际参数,一个对象a,
如果解释表达式(p a)返回一个值(以一个错误消息中止或者是一直运行)
显示出写一个程序halts? 是不可能的,对于任何的p和a,
它要正确的确定p是否停留在a上。使用如下的原因:
如果你有一个程序halts?,你能实现如下的程序:

扫描二维码关注公众号,回复: 3436002 查看本文章

(define (run-forever) (run-forever))

(define (try p)
  (if (halts? p p)
      (run-forever)
      'halted
  )
)

现在考虑解释表达式(try try)并且显示任何可能的输出(停止或者是永远)
违反了halts?的目的行为。

猜你喜欢

转载自blog.csdn.net/gggwfn1982/article/details/81865946