The background here is that I have a non-destructive version of a function that I want to make destructive for performance reasons. However, writing unit tests gets challenging because lisp considers all quoted lists in the source code to be constants and changing those leads to undefined behaviour.
I'm using parachute as the unit testing framework
e.g.,
(define-test suite-1
(let ((start '((1 2) (3 4) (5 6)))
(end '((7 1 2) (3 4) (5 6))))
(is #'equal end (push 7 (car start))))
(let ((start '((1 2) (3 4) (5 6)))
(end '((8 1 2) (3 4) (5 6))))
(is #'equal end (push 8 (car start)))))
This kinda fails because we end up pushing 8
onto the constant list (1 2)
which eventually causes (push 8 (car start))
to result in (8 7 1 2)
instead of the expected (8 1 2)
This isn't a problem with testing non-destructive functions because they don't modify constants. This is also not a problem outside of unit tests because I know that the original structure will no longer be needed.
I could replace the above with this ugly thing :-
(let ((start (list (list 1 2) (list 3 4) (list 5 6))) ...
which then creates a proper non-constant list but it sure does make the code unreadable...
Any suggestions on how other people approach this?
CodePudding user response:
Use COPY-TREE
to make a deep copy of the quoted list structure.
(let ((start (copy-tree '((1 2) (3 4) (5 6)))))
...
)