重复列表的元素与复制

Mar*_*ark 2 lisp list common-lisp repeat

我需要重复列表的每个元素N次,即执行这种转换:

(1 2 3) => (1 1 1 2 2 2 3 3 3) ; N = 3
Run Code Online (Sandbox Code Playgroud)

保持元素的顺序很重要,即第一个元素应该重复N次,然后是第二个,等等.

到目前为止,这是我最好的尝试:

(defun my-fnc (lst &optional (n 2))
  (mapcan (lambda (x) (make-list n :initial-element x))
          lst))
Run Code Online (Sandbox Code Playgroud)

看起来很有效:

CL-USER> (defparameter *foo* '("foo" "bar"))
*FOO*
CL-USER> (setf *foo* (my-fnc *foo* 3))
("foo" "foo" "foo" "bar" "bar" "bar")
Run Code Online (Sandbox Code Playgroud)

......但不完全.问题是前三个元素是对同一个对象的引用.

("foo" "foo" "foo" "bar" "bar" "bar")
;{---------------} {---------------}
; the same string   the same string
Run Code Online (Sandbox Code Playgroud)

这不是我想要的.

所以我的问题是:如何以大多数惯用的方式解决问题,以便结果列表的每个元素都可以引用复制的单独对象.

sds*_*sds 7

这通常是不可能的,因为Common Lisp不提供通用的复制功能.此外,

  • 一些对象是立即的(例如fixnum),并且不能以任何有意义的意义复制
  • 一些对象是不可变的,复制它们是一种浪费
  • 某些对象是嵌套的,您必须决定是要复制还是浅复制

但是,如果您已经解决了问题并提供了复制功能,那就不难了:

(defun my-fnc (list &key (repeat 2) copy-function)
  (mapcan (if copy-function
              (lambda (x) 
                (loop :repeat repeat :collect (funcall copy-function x)))
              (lambda (x) (make-list n :initial-element x)))
          list)) 
Run Code Online (Sandbox Code Playgroud)

请注意,参数的所有元素list都被复制,即返回值与参数没有交集(在eq测试下并假设copy-function返回一个对象)