2011-01-31 149 views
2

我试图完成这个练习;Lisp练习涉及列表操作

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))) 

插入函数似乎自行工作正常,但它似乎不会对循环做任何事情。我是新的lisp和任何帮助将不胜感激,在此先感谢。

回答

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)) 
2

主要问题与您insertIndex功能是,loopdo条款是副作用而已,它不会改变loop的返回值。 (并且您的insert不存在副作用。)将元素添加到列表返回值的右边loop子句是collect。 (也有appendnconc加入多个列表。)

这是一个工作功能:

(defun insert-index (list) 
    (loop for elt in list and i from 1 
    collect elt 
    collect i)) 

你约的insertinsertIndex功能的行为整体预期似乎是有缺陷的。你需要得到一个更清晰的心理模型,即关于哪些功能是副作用的,哪些不是,以及是否需要副作用来解决某些特定问题。

此外,您不应该在Common Lisp中的未定义变量上调用setq。您需要首先使用let来引入一个新的局部变量。

小问题:CamelCase在Lisp中非常单一。在标识符中分离单词的惯用方式是使用破折号,就像我在代码示例中所做的那样。你不需要做(eql something nil),有特殊的null函数来检查是否有东西nil,例如, (null something)