Ошибка схемы рекурсии - PullRequest
       9

Ошибка схемы рекурсии

1 голос
/ 14 ноября 2010

Эта рекурсивная функция, кажется, работает правильно, добавляя в список результатов точные буквы, которые я хочу, B и C, и затем, когда она завершает, она правильно видит, что последний элемент был достигнут.

Затем выполняется базовый вариант, и возникает ошибка, которую я не могу объяснить. Что вызывает эту ошибку?

    (define(preceding-R X Vector result)    
      (if (eq? '() (cdr (vector->list Vector)))
               result
              (helper X Vector result)))

(define (helper X Vector result)
   (if(eqv? X (cadr (vector->list Vector))) ((set! result (cons result (car (vector->list Vector)))) (preceding-R X (list->vector (cdr (vector->list Vector))) result))
                            (preceding-R X (list->vector (cdr (vector->list Vector))) result)))

(preceding-R 'a #(b a c a) '()))

Ошибка:

процедура применения: ожидаемая процедура, учитывая: #; аргументы были: (((). б). в)

Ответы [ 2 ]

4 голосов
/ 14 ноября 2010

Вот код, который не является «абсолютно ужасным»:

(define preceding-R 
  (lambda (x vec)
    (define helper
      (lambda (ls)
        (cond
          ((null? ls) '())
          ((null? (cdr ls)) '())
          ((eq? (cadr ls) x) (cons (car ls) (helper (cdr ls))))
          (else (helper (cdr ls))))))
    (helper (vector->list vec))))

> (preceding-R 'a #(b a c a))
(b c)

Эли Барзилай имеет точку; если бы я оценивал исходный код, я бы, вероятно, присудил бы менее половины кредита из-за того, что он указал:

  • set! следует избегать в большинстве случаев и, как правило, не разрешается при выполнении домашних заданий, связанных с базовым кодом Схемы. Необходимость использования set! - это обычное сообщение о том, что рекурсия не совсем понятна.
  • Поскольку begin «отбрасывает» результаты всего, кроме последнего выражения, это означает, что нехвостовые выражения имеют побочные эффекты (например, set!), поэтому begin обычно не отображается в проблемы образования тоже.
  • Преобразование туда-сюда снова и снова, снова и снова, очевидно, является пустой тратой. Подойдет одно преобразование, но вы, вероятно, могли бы использовать списки вместо векторов для начала. Списки являются наиболее распространенной структурой данных, используемой в Scheme, тем более что они хорошо работают с рекурсией.
  • Ваш код будет содержать ошибку в пустом списке во второй строке: (preceding-R 'a #()) => Error: Attempt to apply cdr on '()
  • Если вы делаете , используете set! для изменения результата, то нет причин для передачи результата. Это дополнительный багаж.
  • Последнее замечание Элая было то, что вы можете написать:

.

(define (helper X Vector result)
  (preceding-R X (list->vector (cdr (vector->list Vector)))
               (if (eq? X (cadr (vector->list Vector)))
                   (cons (car (vector->list Vector)) result)
                   result)))

сохранение некоторого повторного кода.

1 голос
/ 14 ноября 2010
(define (preceding-R X Vector result)    
  (if (eq? '() (cdr (vector->list Vector)))
    result
    (helper X Vector result)))

(define (helper X Vector result)
  (if (eqv? X (cadr (vector->list Vector)))
    (begin
      (set! result (cons (car (vector->list Vector)) result))
      (preceding-R X (list->vector (cdr (vector->list Vector))) result))
    (preceding-R X (list->vector (cdr (vector->list Vector))) result)))

(preceding-R 'a #(b a c a) '())

Я добавил начальный звонок. Если вам нужно несколько выражений, если вы не можете просто обернуть их в (), это интерпретировалось как вызов функции для void (возвращаемый set!) С аргументом, возвращаемым рекурсивным вызовом previous-R.

...