类方法不能用于andmap?

时间:2018-04-09 23:07:00

标签: scheme lisp racket

在处理用于管理员工时间表的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))

我喜欢修复自己的问题所以我查找了给定的错误消息。我没有找到任何相关的东西。这导致了以下问题:为什么andmapmap等可以使用类的方法来处理其过程参数?

PS:实际的类要复杂得多,但这是一个最小的,可验证的例子。 :)

1 个答案:

答案 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包装;目前的实施故意不这样做,但我不确定原理是什么。