在处理用于管理员工时间表的Racket程序时,我发现我不能使用类andmap
的成员方法。
#lang racket
(define example%
(class object%
(super-new)
(define/public (is-even? n)
(even? n))
(define/public (test)
(println
;; Next line causes error.
(andmap is-even? '(2 3 4))))))
;; if the following line is used, everything works properly
;;(andmap even? '(2 3 4))))))
(let ([tmp (new example%)])
(send tmp test))
DrRacket在尝试运行这个简单程序时给出以下错误消息:
类:误用方法(不在应用程序中):is-even?
我当然不会需要来使用andmap
...这只是一种奢侈,因为我可以将lambda和map
的结果输入addmap
并获得相同的功能......
不幸的是,这也不起作用,给出与前一个程序相同的错误......
#lang racket
(define example%
(class object%
(super-new)
(define/public (iseven? n)
(even? n))
(define/public (test)
(println
(let ([true? (lambda
(v)
(equal? v #t))])
(andmap true?
;; map also refuses to use my class's method...
;; so much for my hacky workaround idea.
(map iseven? '(2 3 4))))))))
(let ([tmp (new example%)])
(send tmp test))
我喜欢修复自己的问题所以我查找了给定的错误消息。我没有找到任何相关的东西。这导致了以下问题:为什么andmap
,map
等可以使用类的方法来处理其过程参数?
PS:实际的类要复杂得多,但这是一个最小的,可验证的例子。 :)
答案 0 :(得分:2)
在Racket中,一个方法实际上是由一个重写
的宏实现的(method arg ...)
到
(method-impl this arg ...)
其中method-impl
绑定到方法实现本身(如果方法是私有的或最终的)或某些代码从类的vtable中获取正确的方法实现。
您可以直接扩展方法名称,如下所示:
(andmap (lambda (x) (is-even? x)) xs)
或者您可以使用for/and
:
(for/and ([x (in-list xs)]) (is-even? x))
您只需在操作员位置使用is-even?
(或任何其他方法名称)。
至于为什么Racket的类库以这种方式工作:我不确定。可以将方法名称用作表达式(即,不在操作员位置)自动进行lambda
包装;目前的实施故意不这样做,但我不确定原理是什么。