我正在尝试一些有趣的方案。我正在尝试创建一个Area函数来获取它正在操作的东西的类型,然后根据对象的类型调用不同的函数。这是我的代码:
(define (area object)
(if (not (null? (eval (word 'area- (get-type object)))))
(eval (list (word 'area- (get-type object)) 'object))
#f
)
)
Scheme不喜欢这个,因为它说对象是一个未绑定的变量。不,我不能把报价拿走,因为它实际上是把值放在那里,然后Scheme抱怨列表格式不正确。
如何在eval中使用object中的值?
注意:Scheme显然抓住全局变量“object”就好了,所以它基本上忽略了它在函数内部。
相关语言的一些信息在这里:http://docs.racket-lang.org/guide/eval.html,这似乎表明Scheme中没有解决方案,但如果你知道我想听到的那个。
答案 0 :(得分:3)
没有一个 - 这是一个功能。 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)
但是第一个可能是更典型的类似OO的系统,有一种获取方法的方法,所以它可能对你有用。那个方向可以带你去:
(define (area object)
((get-method object 'get-area) object))
答案 1 :(得分:2)
球拍有classes and methods,您应该使用它!
(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
很多比基于名称的派遣更少hacky。
答案 2 :(得分:0)
显然,有一种方法可以做我想在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部分不起作用,因为尝试获取不存在的函数的标识会导致未绑定的变量错误。因此,仍然需要小心地在支持它的类型上调用操作符。