I want to write a function in Common Lisp, which destructively modifies its argument. In C or Rust I would use a pointer/reference to an object, which can be dereferenced inside the body of the function. In CL I write:
(defun foo (lst)
(setf lst NIL))
But after evaluating this form:
(let ((obj (list "a" "b")))
(foo obj)
obj) => ("a" "b")
one sees that the function foo
has no effect. I can explain that by pass by value semantic, where we modify a local copy of the argument pushed onto the function stack. If we define another function:
(defun bar (lst)
(setf (car lst) NIL))
and evaluate a similar form
(let ((obj (list "a" "b")))
(bar obj)
obj) => (NIL "b")
we will clearly see that the lst
was modified as if we would use the pass by reference semantic. So, (setf lst NIL)
did not worked but (setf (car lst) NIL)
did. Could you please explain why?
For some operations the usual style is this:
(let ((obj (list "a" "b")))
(setf obj (nbar obj)) ; nbar is destructively modifying the list argument
(foo obj))
Above uses SETF
to use the return value to change the binding of obj
, since the function nbar
itself can't do it.
Since NBAR
has no access to the lexical variable obj
and thus can't change it, one is supposed to return the object from NBAR
and then one sets the variable to the result value - overwriting the previous binding.
Examples, where this rule is applicable: calls to sort
, nreverse
, ...
Common Lisp passes arguments by value, but in most cases (other than primitive value types like fixnums or floats) the value is a reference. This is the same way that most managed languages work (eg Java, Python, JS).
In the LET
-form, the value of the variable OBJ
is a reference to a list, not the list itself. That reference is passed by value, so that inside the functions, the value of the parameter LST
is another reference to the same list.
In FOO
, the reference value is replaced with NIL
, but the list that was previously referred to is not touched at all. In BAR
, the list is retrieved from the heap and its CAR
is replaced with NIL
. Since OBJ
holds a reference to the same list, the modification affects it as well.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.