在方案中实现和映射功能,可用于任意数量的列表

时间:2019-03-11 18:23:28

标签: scheme racket

我遇到了实现 andmap 方案功能-andmap proc的问题。

输出应该是:

enter image description here

现在,我有一个用于andmap func的代码,但是对于一个以上的列表来说,这并不是一件好事。

我的代码:

(define (andmap1 pred lox)
(foldr (lambda (x y) (and x y)) true (map pred lox)))

我的输出: enter image description here

有人可以帮我吗? 谢谢

2 个答案:

答案 0 :(得分:3)

您尝试实现andmap的方式存在一个概念性问题。它应该是短路评估,这意味着它必须在找到false值后立即停止,并且返回值是评估输入中最后一个表达式的结果。

这就是为什么(map pred lox)部分一旦到达(andmap1 positive? '(1 -2 a))就会因a示例而失败,并且无论如何foldr将尝试使用整个输入列表-我们不希望这些事情发生。

考虑到以上考虑因素,再加上对多个输入列表进行操作的要求,解决方案发生了很大变化:

(define (andmap1 pred . lox) ; lox is a variable-length list of lists
  (let loop ((lst lox)) ; iterate using a named `let`
    (cond ((or (null? lst) (null? (car lst))) ; if the input is empty
           true) ; then the result is `true`
          ((null? (cdar lst)) ; if there's a single element left in sublists
           (apply pred (map car lst))) ; return pred applied to all
          ((not (apply pred (map car lst))) ; if current elements fail pred
           false) ; short-circuit and return `false` immediately
          (else (loop (map cdr lst)))))) ; advance recursion on all sublists

它按预期工作:

(andmap1 positive? '(1 2 3))
=> #t

(andmap1 positive? '(1 2 a))
=> positive?: contract violation expected: real? given: 'a

(andmap1 positive? '(1 -2 a))
=> #f

(andmap1 + '(1 2 3) '(4 5 6))
=> 9

答案 1 :(得分:0)

这是您编写它的另一种方法,但是请注意,由于使用了foldl,因此它没有提前退出的行为。如我们所见,实现由mapand的折叠组成-

(define (andmap f . ls)
  (foldl (lambda (x acc) (and acc x))
         #t
         (apply map
                (lambda xs (apply f xs))
                ls)))

(andmap positive? '(1 2 3)) ; #t

(andmap + '(1 2 3) '(4 5 6)) ; 9