我有以下过滤程序:
; (2) filter
(define (filter test sequence)
; return a list of the elements that pass the predicate test
(let ((elem (if (null? sequence) nil (car sequence)))
(rest (if (null? sequence) nil (cdr sequence))))
(cond ((null? sequence) nil)
((test elem) (cons elem (filter test rest)))
(else (filter test rest)))))
下面是一个使用它返回列表的偶数元素的示例:
(define even? (lambda (x) (= (modulo x 2) 0)))
(define sequence '(1 2 3 4 5 8 9 11 13 14 15 16 17))
(filter even? sequence)
; (2 4 8 14 16)
有没有一种简单的方法来使用 not
测试来反转选择?例如,我认为以下可能有效:
(filter (not even?) sequence)
但它返回一个错误。我当然可以单独定义odd
:
(define odd? (lambda (x) (not (even? x))))
但我尽量不这样做。有没有办法编写 odd
过程而不直接定义它,而是像我上面尝试的那样直接使用 not
?
最佳答案
有一个complement
Common Lisp 中的函数可以满足我的需求。 complement
是一个高阶过程,它接受一个过程作为其参数,并返回一个过程,该过程采用与输入过程相同的参数并执行相同的操作,但返回的真值是相反的。
Racket 也有类似的程序,negate
,并且在 Scheme 中很容易实现:
(define (complement f)
(lambda xs (not (apply f xs))))
> (filter even? '(1 2 3 4 5))
(2 4)
> (filter (complement even?) '(1 2 3 4 5))
(1 3 5)
> (> 1 2 3 4 5)
#f
> ((complement >) 1 2 3 4 5)
#t
在 Racket 中:
scratch.rkt> (filter even? '(1 2 3 4 5))
'(2 4)
scratch.rkt> (filter (negate even?) '(1 2 3 4 5))
'(1 3 5)
scratch.rkt> (> 1 2 3 4 5)
#f
scratch.rkt> ((negate >) 1 2 3 4 5)
#t
关于scheme - 如何在这里反转谓词?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67796513/