#list #loops #if-statement #lisp #common-lisp
#Список #циклы #Оператор if #lisp #common-lisp
Вопрос:
В настоящее время я пишу небольшую программу на LISP, которая будет принимать список и разделять его следующим образом:
(split '(1 2 3) returns-> ((1 2) (3))
(split '(1 2 3 4) returns-> ((1 2) (3 4))
Я чувствую, что я очень близок, и у меня есть основная логика, моя проблема в том, что я должен выполнить 2-3 действия, если оператор if оценивает значение T. Из-за этого я продолжаю получать ошибку
Ошибка (ы), предупреждение (ы): *** — SYSTEM::%EXPAND-FORM: (PUSH (CAR LST) (CDR (LAST NEWLST))) должно быть лямбда-выражением
Когда оператор if принимает значение true, мне нужно добавить начало текущего списка в конец моей переменной списка newLst, затем мне нужно взять конец текущего списка и установить для него значение моей другой переменной списка new2Lst . После этого мне нужно выйти из цикла и добавить два списка друг к другу. Это, вероятно, не имеет особого смысла, извините, надеюсь, код имеет больше смысла, пожалуйста, найдите его ниже. Заранее благодарю всех вас за помощь, я действительно ценю каждую ее часть!
(defun split (lst)
(cond ((= (list-length lst) 1) lst)
(t (setq w (list-length lst))
(setq newLst (list (car lst)))
(setq new2Lst '())
(loop for x from 1 to ( w 1) do
(if (= x (ceiling (/ w 2)))
( (push (car lst) (cdr( last newLst))) (setq new2Lst (cdr lst)) (return))
(push (car lst) (cdr( last newLst)))
)
(setq lst (cdr lst))
)
(append (list newLst) (list new2Lst))
)
)
)
Комментарии:
1. Переменные w, newlst и new2lst не определены. Вам нужно их определить.
Ответ №1:
progn
Когда вы хотите иметь последовательность выражений a
, b
, c
для вычисления, вам нужно поместить их в (progn a b c)
форму. Но здесь они были завернуты в список форм: когда вы оцениваете (a b c)
в обычном контексте оценки, т. Е.. ожидается, что не в макросах, специальных формах, …, a
будет вызываться функция с аргументами b
и c
. Вот почему у вас есть эта конкретная ошибка: (push ...)
действительно не является именем функции или лямбда-выражением.
Неопределенные переменные
Вы вызываете setq
символы, которые не привязаны к известным переменным, по крайней мере, в вашей функции. Затем большинство реализаций обрабатывают присвоение как присвоение symbol-value
символа, даже если поведение не определено. Вы должны скорее объявлять их в своей функции, имея let
привязку:
(let ((w (length list))
(... ...))
...)
Кстати, вы вычисляете длину списка дважды в этой функции, длина может быть вычислена только один раз, и на самом деле вам нужно только знать, есть ли в списке один элемент и нет ли списка в его cdr: это вычисление с постоянным временем, в отличие list-length
от которого требуется пройти весь списоксписок.
Имена переменных, регистр
Будьте осторожны с тем, как вы называете свои переменные, и, пожалуйста, придерживайтесь соглашений Lisp, используя hyphen-separated-words
вместо сочетания верхнего и нижнего регистра.