Просто пытаюсь рекурсивно напечатать список, но ничего не печатает - PullRequest
1 голос
/ 27 июня 2011

Я хотел бы просмотреть список (который может иметь вложенные списки) и сделать так, чтобы он оценивался в один плоский список со всеми элементами.Я даже не могу получить рекурсивную функцию для оценки чего-либо, кроме nil

(defun pl(lst)
  (if (atom lst)
      lst
    (progn
      (pl (car lst))
      (pl (cdr lst)))))

Затем я вызову что-то вроде (pl '(1 (2 3) (4 5))), но оно всегда оценивается как nil.

Я изменил

(if (atom lst) lst

на

(if (atom lst) (print lst)

, и это даже не печатает ни один из пунктов списка.

что я за концепцияздесь отсутствует?

Ответы [ 2 ]

4 голосов
/ 27 июня 2011

Функция обычно возвращает только одно значение, которое является значением ее тела.Если вы внимательно посмотрите на pl, то увидите, что это форма if, поэтому pl либо возвращает значение lst, либо значение progn.

Первое, на что я должен указать, это то, что возвращаемое значение формы (progn ...) является значением ее последнего выражения, которое в данном случае является рекурсивным вызовом (pl (cdr lst)).Поскольку вы ничего не делаете с возвращаемым значением (pl (car lst)), этот вызов не оказывает никакого влияния .Значение рекурсивного вызова в какой-то момент упадет до теста atom.Второе, на что следует обратить внимание, это то, что (atom nil) также верно.Помните, что последний элемент списка - nil, поэтому, когда вы дадите pl список, он будет всегда возвращать ноль , как вы заметили.

Если ваша версия для печати ничего не показываетВозможно, это связано с тем, что выходные данные для печати отображаются где-то еще, например, в другом буфере.

Что касается решения: вы либо хотите получить чисто рекурсивное решение, используя append вместо progn, потому что эточто в вашем домашнем задании.В обычном lisp вы просто используете одну из конструкций итерации.

Мой совет - проверить любой учебник по lisp или схеме, чтобы понять основы рекурсии и хвостовой рекурсии.

1 голос
/ 28 июня 2011

Возможно, вы захотите посмотреть вводный текст, например " Маленький интриган ". Первое, что он делает, это показывает вам, как придерживаться единого подхода к решению проблем, подобных этому. Результирующая функция может выглядеть так:

(define (pl lst)
  (cond ((null? lst) '())
        ((not (pair? lst)) (list lst))
        (else (append (pl (car lst))
                      (pl (cdr lst))))))

Конечно, это Схема, но подход к Лиспу тот же:

  • Проверка для особого случая, когда аргумент равен nil
  • Проверка на особый случай, когда аргумент является атомом
  • Рекурсивно применить функцию к машине и cdr аргумента, добавив результаты

Та же функция в Лиспе будет выглядеть так:

(defun pl (lst)
   (cond ((null lst) '())
         ((atom lst) (list lst))
         (t (append (pl (car lst))
                    (pl (cdr lst))))))

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

...