Лисп-упражнения с использованием списка - PullRequest
2 голосов
/ 31 января 2011

Я пытаюсь выполнить это упражнение;

Write a Lisp function that takes as input a list of elements, such as (A B C)

и возвращает список, в котором позиция каждого элемента следует за ним, например (A 1 B 2 C 3)

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

(defun insert (index var userList)
    (if (or (eql userList nil) (eql index 1))
            (cons var userList)
            (cons (car userList) (insert (- index 1) var (cdr userList)))))


(defun insertIndex (userList)
    (setq len (length userList))
    (loop for x from 1 to len
        do (insert x x userList)))

Кажется, что функции вставки работают нормально сами по себе, но кажется, что они ничего не делают с циклом. Я новенький, и любая помощь будет признательна, спасибо заранее.

Ответы [ 2 ]

3 голосов
/ 31 января 2011

Позиции в Лиспе начинаются с 0. В insertIndex переменная len не определена.LOOP не возвращает никакого полезного значения.

Если вы хотите решить его с помощью рекурсии, решение намного проще.

Вам необходимо проверить конечное условие.Если список пуст, вернуть пустой список.

В противном случае создайте новый список с элементом FIRST, текущей позицией и результатом вызова функции в остальной части списка и позицией, увеличенной на единицу.

(LIST* 1 2 '(3 4)) is shorter for (cons 1 (cons 2 '(3 4))).

Вот пример с локальной функцией.Создать функцию верхнего уровня с помощью DEFUN теперь ваша задача.Вам нужно только немного переписать код.LABELS представляет потенциально рекурсивную локальную функцию.

(labels ((pos-list (list pos)
           (if (null list)
               '()
               (list* (first list)
                      pos
                      (pos-list (rest list) (1+ pos))))))
  (pos-list '(a b c d e f) 0))
2 голосов
/ 03 февраля 2011

Основная проблема с вашей функцией insertIndex заключается в том, что предложение do в loop предназначено только для побочных эффектов, оно не меняет возвращаемого значения loop.(И ваш insert не имеет побочных эффектов.) Правильное предложение loop для добавления элементов в возвращаемое значение списка - collect.(Есть также append и nconc для объединения в несколько списков.)

Это рабочая функция:

(defun insert-index (list)
  (loop for elt in list and i from 1
    collect elt
    collect i))

Ваши ожидания относительно поведения insert иinsertIndex функции кажутся некорректными.Вам нужно получить более ясную мысленную модель о том, какие функции являются побочными, а какие нет, и нужны ли вам побочные эффекты или нет для решения какой-то конкретной проблемы.

Кроме того, вам не следует звонить setq для неопределенной переменной в Common Lisp.Сначала вам нужно использовать let, чтобы ввести новую локальную переменную.

Незначительные точки: CamelCase очень недиоматичен в Лиспе.Идиоматический способ разделения слов в идентификаторах - использовать тире, как я делал в своем примере кода.И вам не нужно делать (eql something nil), есть специальная функция null, чтобы проверить, является ли что-то nil, например, (null something).

...