2

thanks for your support, I am a newbie... I would like to swap elements BETWEEN two lists in Common-LISP given a certain index of the first and second list, for example: (1 2 3 4) (A B C D) -> (D 2 3 4) when specified indexes are (0 3).

It might look randomish but it has a nice utility in musical sequences... Thanks, Alessandro

  • If you want to mutate the lists, [`ROTATEF`](http://www.lispworks.com/documentation/HyperSpec/Body/m_rotate.htm) should work. – jkiiski Jul 06 '18 at 11:02
  • 1
    That's a duplicate: https://stackoverflow.com/questions/3950601/swapping-elements-in-a-common-lisp-list#3950697 – Ehvince Jul 06 '18 at 14:01
  • 1
    Possible duplicate of [Swapping elements in a Common Lisp list](https://stackoverflow.com/questions/3950601/swapping-elements-in-a-common-lisp-list) – coredump Jul 06 '18 at 19:51

1 Answers1

6

If you need to use an index, maybe a vector can be more sensible. Use for example ROTATEF, as explained by jkiiski:

CL-USER> (let ((a (vector 1 2 3 4))
               (b (vector 'a 'b 'c 'd)))
           (rotatef (aref a 0) (aref b 3))
           (values a b))
#(D 2 3 4)
#(A B C 1)

If you really want to use lists, then use NTH, or ELT, which works on both kinds of sequences.

Preemptive remark: you cannot modify constant data. Note how vectors a and b are allocated at runtime. Constant data is data that was computed at read-time or compile-time, and should not be modified at runtime. Quoted lists are constant, as shown by this example:

CL-USER> (let ((list '(a b))) (setf (first list) 0) list)
; in: LET ((LIST '(A B)))
;     (SETF (FIRST LIST) 0)
; ==>
;   (SB-KERNEL:%RPLACA LIST 0)
; 
; caught WARNING:
;   Destructive function SB-KERNEL:%RPLACA called on constant data: (A B).
;   See also:
;     The ANSI Standard, Special Operator QUOTE
;     The ANSI Standard, Section 3.2.2.3
; 
coredump
  • 37,664
  • 5
  • 43
  • 77