Разрыв из цикла через оператор if LISP

#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 вместо сочетания верхнего и нижнего регистра.