Как рекурсивно добавлять элементы в список на основе оценки другой функции в схеме - PullRequest
0 голосов
/ 26 октября 2018

У меня есть следующий код, в котором я пытаюсь добавить все элементы списка в новый список, основываясь на том, являются ли они простыми числами:

(define (findPrimes newLis lis)
    (cond
            ((null? lis) ())
            (else 
                (
                    (cond 
                        ((#t (isPrime (CAR lis)))
                            (append newLis (CAR lis))))
                    (findPrimes newLis (CDR lis))
              ))
          )

        newLis
    )

Я, однако, получаю ошибку. Я чрезвычайно новичок в схеме, поэтому я прошу прощения, если этот код полностью неверен.

1 Ответ

0 голосов
/ 26 октября 2018

Да, у вас много лишних скобок.Каждая пара скобок имеет значение, в Схеме, мы не можем просто просмотреть их для хорошей меры.(f x) означает "вызвать функцию f с аргументом x" , поэтому ((f x)) означает "вызвать функцию f с аргументом x, а затем обработать результат этого вызова как функцию и вызвать его (снова) без каких-либо аргументов ".Который обязан вызывать проблемы, скорее всего, чем нет.

То, что вы хотели написать, было

(define (findPrimes newLis lis)
    (cond
            ((null? lis)   (set! newLis '()))
            (else 
                (cond 
                   ((equal? #t (isPrime (CAR lis)))
                           (set! newLis 
                                 (append newLis (list (CAR lis))))
                           (findPrimes newLis (CDR lis)))
                   (else
                           (findPrimes newLis (CDR lis)))))))

, но это все виды ошибок.Для начала (findPrimes '() (list 2 3 4 5 6 7 8 9 10)) ничего не возвращает - независимо от аргументов.

Вам нужно изменить обработку базового случая.В рекурсивном случае вы создаете список, переданный в качестве первого аргумента;затем, когда мы достигли конца списка ввода (второй аргумент), что вы будете делать с новым списком, который теперь готов?Вы установили его на '()!И вы не возвращаете никакого значения (потому что set! не возвращает никакого значения).

Так что это легко исправить: просто верните построенное вами значение.Значение последнего выражения - это то, что возвращается как значение всей функции.И у вас есть значение, которое вы хотите вернуть, новый список.Таким образом, вы делаете это последним выражением в базовом случае cond.Так что теперь это работает.

Но это не работает хорошо .Это квадратичное во времени (из-за повторного append).Это обычно означает катастрофически медленное время выполнения.Кроме того, использование set! является индикатором того, что что-то может быть не совсем правильным.

Обычный способ Схемы это сделать,

(define (findPrimes lis)
    (cond
            ((null? lis)               '() )
            (else 
                (cond 
                   (           (isPrime (CAR lis))
                           (cons                      (CAR lis)
                             (findPrimes        (CDR lis))))
                   (else
                             (findPrimes        (CDR lis)))))))

посмотреть, насколько меньше у вас было вещейввести?

Вот и снова, с нормальным интервалом:

(define (findPrimes lis)
  (cond
    ((null? lis) '() )
    ((isPrime (car lis))
     (cons (car lis)
           (findPrimes (cdr lis))))
    (else
     (findPrimes (cdr lis)))))

Была еще одна или две вещи, которые я тоже там изменил.Вы можете сказать, что это было?

...