通过 If 语句 LISP 中断循环

Breaking From Loop Through If Statement LISP

我目前正在用 LISP 编写一个小程序,它将接受一个列表,并将其拆分如下:

(split '(1 2 3) returns-> ((1 2) (3)) 
(split '(1 2 3 4) returns-> ((1 2) (3 4))

我觉得我已经很接近并且已经写出了它的基本逻辑,我的问题是如果 if 语句的计算结果为 T,我必须执行 2 - 3 个动作。因此我一直收到错误

Error(s), warning(s): *** - SYSTEM::%EXPAND-FORM: (PUSH (CAR LST) (CDR (LAST NEWLST))) should be a lambda expression

当 if 语句的计算结果为真时,我需要将当前列表的头部添加到我的列表变量 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))
            ) 
     ) 
)

progn

当你想有一个表达式序列abc来计算时,你需要把它们放在(progn a b c)形式中。但是在这里你将它们包装在一个表单列表中:当你在正常的评估上下文中评估 (a b c) 时,即。不是在宏、特殊形式中,...,a 应该是一个用参数 bc 调用的函数。 这就是为什么你有那个特定的错误: (push ...) indeed is not a function name or a lambda expression.

未定义变量

您正在对未绑定到已知变量的符号调用 setq,至少在您的函数中是这样。大多数实现随后将赋值视为对符号 symbol-value 的赋值,即使未指定行为。您应该通过 let 绑定在您的函数中声明它们:

(let ((w (length list))
      (... ...))
  ...)

顺便说一句,你在这个函数中计算了两次列表的长度,长度可以只计算一次,实际上你只需要知道列表是否有一个元素并且其cdr中没有列表:这是一个 constant-time 计算,不像 list-length 需要遍历整个列表。

变量名,大小写

注意变量的命名方式,请遵守 Lisp 约定,使用 hyphen-separated-words 而不是大小写混合。