Рекурсивный диапазон в Лиспе добавляет точку?

(define ..
  (lambda (start stop)
    (cond ((> (add1 start) stop) (quote ()))
          ((eq? (add1 start) stop) (sub1 stop))
          (else (cons start (.. (add1 start) stop))))))

Я определил простую функцию диапазона. Намерение для

(.. 1 5)  -->  (1 2 3 4)

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

(.. 1 5)  -->  (1 2 3 . 4)

Я не понимаю, почему это происходит. Любая помощь приветствуется

3 ответа

Решение

Список в Схеме - это либо пустой список () (также известен как nil в некоторых Лиспах), или против car (также известен как first) является элементом списка и чей cdr (также известен как rest) либо остальная часть списка (т. е. другой список), либо атом, который завершает список. Условный терминатор - пустой список (); списки завершены () называются "правильные списки". Списки, оканчивающиеся любым другим атомом, называются "неподходящими списками". Список (1 2 3 4 5) содержит элементы 1, 2, 3, 4 и 5 и заканчивается (), Вы могли бы построить это путем

(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))

Теперь, когда система печатает ячейку "против", общий случай состоит в том, чтобы напечатать ее

(car . cdr)

Например, результат (cons 1 2) печатается как

(1 . 2)

Поскольку списки построены из cons-ячеек, вы также можете использовать эту запись для списков:

'(1 2 3 4 5) ==
'(1 . (2 . (3 . (4 . (5 . ())))))

Это довольно неуклюже, однако, поэтому у большинства списков (все, что я знаю) есть особый случай для печати против клеток: если cdr это список (либо другая ячейка минусов, либо ()), то не печатайте .и не печатать окружающие скобки cdr (что было бы иначе, так как это список). Итак, если вы видите результат, как

(1 2 3 . 4)

это означает, что у вас есть неправильный список, который заканчивается атомом 4, Имеет структуру

(1 . (2 . (3 . 4)))

Теперь возникает вопрос: где в вашем коде построение списка пошло не так? .. всегда должен возвращать правильный список, поэтому давайте посмотрим на случаи: первый случай всегда возвращает правильный список (пустой список):

((> (add1 start) stop) (quote ()))

Второй случай выглядит так, как будто он может вернуть что-то, что не является списком (при условии, что (sub1 stop) == (- stop 1)):

((eq? (add1 start) stop) (sub1 stop))

Сейчас если .. работали правильно, тогда третий случай всегда возвращал правильный список (так как (cons x y) правильный список, если y является):

(else (cons start (.. (add1 start) stop)))

Сделайте, чтобы ваш второй случай вернул список, и вы должны быть готовы

Ваше выражение (sub1 stop) нужно читать (list (sub1 stop))

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

Удалить эту часть конд

 ((eq? (add1 start) stop) (sub1 stop))

Это вызывает преждевременное окончание.

Другие вопросы по тегам