Реализовать функцию andmap в схеме для любого количества списков

#scheme #racket

#схема #racket

Вопрос:

У меня возник вопрос по реализации функции схемы andmapandmap 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