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]))