Reputation: 7599
I need to repeat every element of a list N times, i.e. perform this kind of transformation:
(1 2 3) => (1 1 1 2 2 2 3 3 3) ; N = 3
It is important to preserve the order of elements, i.e. first element should be repeated N times, then second, etc.
This is my best attempt so far:
(defun my-fnc (lst &optional (n 2))
(mapcan (lambda (x) (make-list n :initial-element x))
lst))
Looks like it works:
CL-USER> (defparameter *foo* '("foo" "bar"))
*FOO*
CL-USER> (setf *foo* (my-fnc *foo* 3))
("foo" "foo" "foo" "bar" "bar" "bar")
...but not quite. The problem is that former three elements are references to the same object.
("foo" "foo" "foo" "bar" "bar" "bar")
;{---------------} {---------------}
; the same string the same string
This is not what I want.
So my question is: how to solve the problem in most idiomatic way, so that every element of result list would be reference to copied separate object.
Upvotes: 2
Views: 964
Reputation: 60074
This is impossible to do in general because Common Lisp does not provide a generic copy function. Moreover,
fixnum
) and cannot be copied in any meaningful senseHowever, if you have resolved the problem and provided the copy function, it is not too hard:
(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))
Note that all the element of the list
argument are copied, i.e., the return value has no intersection with the argument (under the eq
test and assuming that the copy-function
returns a fresh object)
Upvotes: 7