Lisp练习涉及列表操作

时间:2011-01-31 00:09:15

标签: list lisp common-lisp list-manipulation

我试图完成这个练习;

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 个答案:

答案 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。 (还有collectappend加入多个列表。)

这是一个有效的功能:

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)