#scheme #racket
#схема #racket
Вопрос:
У меня возник вопрос по реализации функции схемы andmap — andmap proc.
Вывод должен быть:
Теперь у меня есть код для функции andmap, но он не подходит для более чем одного списка.
мой код:
(define (andmap1 pred lox)
(foldr (lambda (x y) (and x y)) true (map pred lox)))
кто-нибудь может мне помочь, пожалуйста? Спасибо
Ответ №1:
Существует концептуальная проблема с тем, как вы пытаетесь реализовать 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
Ответ №2:
Вот еще один способ, которым вы можете это написать, но обратите внимание, что у него нет поведения раннего завершения, потому что foldl
используется. Как мы можем видеть, реализация состоит из комбинации map
и сворачивания and
—
(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