Lisp 如何在方案中的评估中使用外部变量?
我正在尝试一些有趣的计划。我试图创建一个区域函数,它获取它所操作的对象的类型,然后根据对象的类型调用不同的函数。这是我的密码:Lisp 如何在方案中的评估中使用外部变量?,lisp,scheme,eval,Lisp,Scheme,Eval,我正在尝试一些有趣的计划。我试图创建一个区域函数,它获取它所操作的对象的类型,然后根据对象的类型调用不同的函数。这是我的密码: (define (area object) (if (not (null? (eval (word 'area- (get-type object))))) (eval (list (word 'area- (get-type object)) 'object)) #f ) ) Scheme不喜欢这样,因为它说object是一个未绑定的
(define (area object)
(if (not (null? (eval (word 'area- (get-type object)))))
(eval (list (word 'area- (get-type object)) 'object))
#f
)
)
Scheme不喜欢这样,因为它说object是一个未绑定的变量。不,我不能把引号拿走,因为它实际上是把值放在那里,然后Scheme抱怨列表格式不正确
如何在eval中使用对象中的值
注意:Scheme显然很好地抓住了全局变量“object”,所以它基本上忽略了它在函数中
这里有一些相关语言的信息:,这似乎表明Scheme中没有解决方案,但如果您知道,我想听听。没有,这是一个特性eval
对运行时动态生成的表单进行评估。因此,如果它需要了解本地绑定,那么您需要以不同的方式编译(lamba(x)x)
和(lambda(y)y)
,因为名称很重要。但这只是一个提示,在实现这种特性方面有一大堆问题
至于你的问题——即使有可能做你想做的事,这也是一个脆弱的解决方案,取决于名字。请记住,在Scheme中,您可以像使用任何其他值一样使用函数——因此,不要调用get type
并将其与某个符号组合以获得名称,而是让您的对象包含所需的函数(此时最好称之为“方法”)
比如:
(define (area object)
((get-area-method object) object))
显然,这样做意味着不完全采用以下方式没有什么意义:
(define (area object)
(get-area object))
这只是
(define area get-area)
但是第一种可能更典型于一般的面向对象系统,它有一种获取方法的方法,因此它可能对您有用。这个方向可以带你去:
(define (area object)
((get-method object 'get-area) object))
没有,这是一个特性eval
对运行时动态生成的表单进行评估。因此,如果它需要了解本地绑定,那么您需要以不同的方式编译(lamba(x)x)
和(lambda(y)y)
,因为名称很重要。但这只是一个提示,在实现这种特性方面有一大堆问题
至于你的问题——即使有可能做你想做的事,这也是一个脆弱的解决方案,取决于名字。请记住,在Scheme中,您可以像使用任何其他值一样使用函数——因此,不要调用get type
并将其与某个符号组合以获得名称,而是让您的对象包含所需的函数(此时最好称之为“方法”)
比如:
(define (area object)
((get-area-method object) object))
显然,这样做意味着不完全采用以下方式没有什么意义:
(define (area object)
(get-area object))
这只是
(define area get-area)
但是第一种可能更典型于一般的面向对象系统,它有一种获取方法的方法,因此它可能对您有用。这个方向可以带你去:
(define (area object)
((get-method object 'get-area) object))
显然,在这个计划中,有一种方法可以实现我想做的事情。代码如下:
(define (area object)
((eval (list 'identity (word 'area- (get-type object)))) object)
)
基本上,技巧是这样的:因为eval只知道全局变量,所以我仍然可以使用eval中的identity函数返回全局变量的值。在这个例子中,我感兴趣的全局变量是一个函数,它和其他变量一样。然后我可以返回这个值,并将其用作调用原始参数的过程。这使我能够构造我想要从全局范围中获取的变量的名称,并获取和使用该变量中包含的过程,从而实现我想要的结果
这里有一个更简洁的版本:
(define (area object)
((get-function (word 'area- (get-type object))) object)
)
(define (get-function function)
(eval (list 'identity function)))
显然,is not null部分将不起作用,但是,因为尝试获取不存在的函数的标识会导致未绑定变量错误。因此,仍然需要小心调用支持它的类型上的运算符。显然有一种方法可以实现我在Scheme中想要做的事情。代码如下:
(define (area object)
((eval (list 'identity (word 'area- (get-type object)))) object)
)
基本上,技巧是这样的:因为eval只知道全局变量,所以我仍然可以使用eval中的identity函数返回全局变量的值。在这个例子中,我感兴趣的全局变量是一个函数,它和其他变量一样。然后我可以返回这个值,并将其用作调用原始参数的过程。这使我能够构造我想要从全局范围中获取的变量的名称,并获取和使用该变量中包含的过程,从而实现我想要的结果
这里有一个更简洁的版本:
(define (area object)
((get-function (word 'area- (get-type object))) object)
)
(define (get-function function)
(eval (list 'identity function)))
显然,is not null部分将不起作用,但是,因为尝试获取不存在的函数的标识会导致未绑定变量错误。因此,仍然需要小心呼叫支持它的类型的操作员。Racket有,您应该使用它
(define circle%
(class object%
(init radius)
(define r radius)
(super-new)
(define/public (area)
(* pi r r))))
(define rectangle%
(class object%
(init width height)
(define w width)
(define h height)
(super-new)
(define/public (area)
(* w h))))
(define unit-circle (new circle% [radius 1]))
(define unit-square (new rectangle% [width 1] [height 1]))
(send unit-circle area) ; => 3.141592653589793
(send unit-square area) ; => 1
比基于姓名的发送要简单得多。Racket有,你应该使用它
(define circle%
(class object%
(init radius)
(define r radius)
(super-new)
(define/public (area)
(* pi r r))))
(define rectangle%
(class object%
(init width height)
(define w width)
(define h height)
(super-new)
(define/public (area)
(* w h))))
(define unit-circle (new circle% [radius 1]))
(define unit-square (new rectangle% [width 1] [height 1]))
(send unit-circle area) ; => 3.141592653589793
(send unit-square area) ; => 1
比基于姓名的发送要简单得多。这是非常错误的。从使用
'identity
是多余的这一事实开始(你可以直接评估符号——同样的结果),然后你就得到了get function
的“干净”版本,它本身只是一个identity函数。但是我如何评估构造的符号呢?可能(eval)(list)(append something?问题是,eval从列表构造一个过程,所以如果我(eval'thing)它真的调用(thing)而不带参数,而不是只返回thing的值。不,那是错误的。(eval'x)
只返回全局x
的值,它不调用任何函数。(但看看我的答案——你不应该用eval
来做这样的事情。这肯定是一个糟糕的解决方案。)很好,我以为eval在评估它,但那是因为我在一个列表中传递它,使eval调用I