I thought function in elisp can't modify its argument, but it is not true when some special primitive functions such as setcar
/setcdr
/delq
/delete
(not including setq
) are called when defining new function in elisp, for example, in following the value of x
gets changed after calling (foo x)
, which is not unexpected and undesired to me.
(defun foo (x) (setcdr x nil))
(progn (setq x '(1 2))
(foo x)
x)
;; => (1)
I know I can make a copy of x
before using setcar
to avoid the problem, is this the right way?
Besides, It also looks like it is impossible to write a setcar
implementation in elisp function.
It bothered me when I was writing my-insert-nth
, I had to make a copy of argument list
in function body since list
's value should be changed, while I'm not quite sure.
(defun my-insert-nth (list element n)
"Insert ELEMENT at Nth of LIST."
(if (<= n 0)
(nconc (list element) list)
(let ((len (length list)))
(if (>= n len)
(append list (list element))
;; FIXME: Why need another copy? Does `defun' already do that?
(let ((new-list (copy-sequence list)))
(setcdr (nthcdr (1- n) new-list) (cons element (nthcdr n new-list)))
new-list)))))
(let ((l '(a b c)))
(list (my-insert-nth l 'beg 0)
(my-insert-nth l 'mid 2)
(my-insert-nth l 'end 3)))
;; => ((beg a b c)
;; (a b mid c)
;; (a b c end))