我试图完成这个练习;
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)))
插入函数本身似乎运行良好,但似乎它对循环没有任何作用。我是新的口齿不清,任何帮助都会受到赞赏,提前谢谢。
答案 0 :(得分:3)
Lisp中的位置以0开头。在insertIndex中,未定义变量len。 LOOP不会返回任何有用的值。
如果你想用递归来解决它,解决方案会简单得多。
您需要测试最终条件。如果列表为空,则返回空列表。
否则创建一个包含FIRST元素的新列表,当前位置以及在列表的其余部分调用该函数的结果,并且位置增加1。
(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))
答案 1 :(得分:2)
insertIndex
函数的主要问题是do
的{{1}}子句仅用于副作用,它不会更改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
函数行为的整体期望似乎存在缺陷。您需要获得更清晰的心理模型,了解哪些功能是副作用的,哪些不是副作用,以及您是否需要副作用来解决某些特定问题。
此外,您不应该在Common Lisp中对未定义的变量调用insertIndex
。您需要先使用setq
来引入新的局部变量。
小点:CamelCase在Lisp中非常单一。在标识符中单独使用单词的惯用方法是使用破折号,就像我在代码示例中所做的那样。而且您不需要执行let
,可以使用特殊的(eql something nil)
函数来检查某些内容是否为null
,例如nil
。 (null something)
。