mapcar lisp 的替代品

Alternative to mapcar lisp

我需要写一个powerset的递归函数,但是我不会用mapcar,loop

到目前为止,这是我的代码:

(defun parts (L)
  (cond 
    ((null L)'(nil))    
    (T
      (let ((PXs (parts (cdr L))))
        (append PXs (add(car L) PXs))
      )
    )   
  )
)

(defun add (E Cs)
  (cond
    (
    (null (cdr Cs))
        (list(cons E Cs))
    )
    (T 
        (append(list(cons E (list (car Cs)))) (addE (cdr Cs)))          
    )   
  )
)

但是 (parts ('1 2 3)) 的结果是:

(NIL (3 NIL) (2 NIL) (2 (3 NIL)) (1 NIL) (1 (3 NIL)) (1 (2 NIL)) (1 (2 (3 NIL))))

我找到了这个方法

(defun powerset (list)
   (let ((x (car list)))
     (if x
       (let ((p (powerset (cdr list))))
         (append p (mapcar (lambda (list) (cons x list)) p)))
      '(()))))

(powerset('1 2 3)) 的结果是:

(NIL (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))

但是我不能使用mapcar,而且我在我的代码中找不到问题,有没有其他功能可以替代mapcar?

这是一个可能的解决方案:

(defun parts (l)
  (if (null l)
      '(())
      (add (car l) (parts (cdr l)))))

(defun add (x pset)
  (if (null pset)
      nil
      (cons (car pset)
            (cons (cons x (car pset))
                  (add x (cdr pset))))))

(parts '(1 2 3))  ;   =>  (NIL (1) (2) (1 2) (3) (1 3) (2 3) (1 2 3))

函数 add 以这种方式将元素 x 添加到幂集中:

  1. 如果powerset为空,则没有什么可添加的;
  2. 否则,通过在幂集中的所有列表中插入或不插入元素来获得新的幂集,因此通过复制其列表数。

函数parts递归地构建一个列表的幂集,方法是在某个时间将它的一个元素添加到由包含空列表的列表构成的幂集中(空集的幂集)。

问题:我们不能使用:

 (mapcar (lambda (list) (cons x list)) p)

解决方案:

 (pairlis (make-list (length p) :initial-element x) p)

也就是说,我们制作了一个长度与p相同的列表,其中包含重复x的值。然后我们 "zip-cons" 这个与 p 使用 pairlis:

 ;; understanding pairlis:
 (pairlis '(a b c) '(1 2 3)) ->  { either: ((a . 1) (b . 2) (c . 3))
                                 { or:     ((c . 3) (b . 2) (a . 1))

pairlis,当只给定两个参数(没有 alist)时,本质上是 (mapcar #'cons list1 list2) 伪装,增加了 list1 的限制和 list2 必须是相同的长度,并且结果可以向前或向后排序。