Racket 如何使自己的andmap功能短路?

Racket 如何使自己的andmap功能短路?,racket,Racket,我有: 为了 我得到了正确的答案 然而,当我提出: (andmap1 positive? (list 1 -1 2)) 我犯了一个错误。 如果pred和列表中的元素不匹配,如何使函数停止?(pred可以是任何谓词)您的和map1很好,已经短路了 (andmap1 positive? (list false 1)) 此处短路的含义是,如果x是列表中y之前的一个元素,并且(px)的计算结果为false,则将不计算(py)。在我上面的例子中,(正值?“Hi”)没有计算,因为(p-1)已经计算为fa

我有:

为了

我得到了正确的答案

然而,当我提出:

(andmap1 positive? (list 1 -1 2))
我犯了一个错误。
如果pred和列表中的元素不匹配,如何使函数停止?(pred可以是任何谓词)

您的
和map1
很好,已经短路了

(andmap1 positive? (list false 1))
此处短路的含义是,如果
x
是列表中
y
之前的一个元素,并且
(px)
的计算结果为false,则将不计算
(py)
。在我上面的例子中,
(正值?“Hi”)
没有计算,因为
(p-1)
已经计算为false

例如,将计算
(正值?
),因为
“Hi”
之前没有元素在应用于
正值?
时返回false。而且因为<代码>正面的合同是<代码>编号?->数字?,您得到了一个违反合同的错误(因为
“Hi”
不是一个数字)

但是,如果您希望像
(和map1阳性?(列出“Hi”1))
这样的东西能够正常工作而不会导致错误,该怎么办

一种可能是放松
积极?
,这样就不会导致违反合同的错误

> (andmap1 positive? (list -1 "Hi"))
#f
然后:

另一种可能是处理
和MAP1中的错误:

> (andmap1 my-positive? (list "Hi" 1))
#f

一般来说,您不能:处理错误可以解决部分问题,但不能解决全部问题。你不能去的原因很重要。为了能够在调用某个参数的过程之前停止,您必须能够回答两个问题:

  • 有了这个论点,这个程序会不会引发某种例外
  • 有了这个论点,这个过程会失败吗
正如你所说,这个过程可以是任何过程。如果第一个是真的,那么如果你能处理错误,你就能处理问题。但是如果第二个是真的,这对你没有帮助

这些问题是著名的,(显然,这个链接不是这一点的原始证明,但它是一个可爱的描述)

如果你已经知道有一些你的谓词不喜欢的参数,你最好的希望是用某种保护措施来包装它,这会导致它在这些参数上失败。您可以通过传递另一个显式检查的谓词来实现,也可以提供可选的“guard”谓词:

(define (andmap1 pred lst)
  (cond
    [(empty? lst) true]
    [else 
     (with-handlers ([exn:fail? (lambda (e) #f)])
       (cond
         [(pred (first lst)) (andmap1 pred (rest lst))]
         [else false]))]))

> (andmap1 positive? (list "Hi" 1))
#f
现在
(andmap1正数?'(1 2 3“x”)
将引发错误,但是
(andmap1正数)(1 2 3“x”)#:保护整数?
将只返回
#f

(andmap1 positive? (list false 1))
> (andmap1 positive? (list -1 "Hi"))
#f
;; my-positive? :: any/c -> boolean?
(define (my-positive? x)
  (and (number? x) (positive? x)))

> (my-positive? "Hi")
#f
> (my-positive? -1)
#f
> (my-positive? 1)
#t
> (andmap1 my-positive? (list "Hi" 1))
#f
(define (andmap1 pred lst)
  (cond
    [(empty? lst) true]
    [else 
     (with-handlers ([exn:fail? (lambda (e) #f)])
       (cond
         [(pred (first lst)) (andmap1 pred (rest lst))]
         [else false]))]))

> (andmap1 positive? (list "Hi" 1))
#f
(define (andmap1 pred lst #:guard (guard #f))
  (define effective-pred
    (if guard
        (λ (x)
          (and (guard x) (pred x)))
        pred))
  (cond
    [(empty? lst) true]
    [(effective-pred (first lst))
     (andmap1 effective-pred (rest lst))]
    [else false]))