TheEnt
TheEnt

Reputation: 496

Which object the function nth access to when applied to functional argument in Common Lisp?

I have some problem using accessor function nth. I pass a list to some function and make new binding to an element of the list in the function with nth, then when I call the list out of the function, it is modified, and it's not what I want! What happens?

Some examples

(defun test (x) (incf x)) => TEST
(setq a 1) => 1
(test a) => 2
a => 1

I understand what's going on above, but if we change everything to lists, something happens that I can't understand

(defun test (x) (incf (nth 0 x))) => TEST
(setq a '(1)) => (1)
(test a) => 2
a => (2)

I expected a to be (1), why it has been modified? I also tried other functions like car and first, result is the same.

PS, I tried it in Lispworks and SBCL, same result.

Upvotes: 2

Views: 105

Answers (3)

jwmc
jwmc

Reputation: 561

If you don't want anything to be modified, don't use incf. Use 1+. The only reason to use incf is because you want its side-effect.

As to why this is happening, arguments are evaluated before being passed to a function. When you call test with a being 1, you are passing the value 1, which cannot be modified. When a resolves to a list, you are passing a list, which can be setf'd all over the shop, if you've chosen to use destructive functions.

Upvotes: 3

Rainer Joswig
Rainer Joswig

Reputation: 139261

(defun test (x) (incf x)) => TEST
(setq a 1) => 1
(test a) => 2
a => 1

You pass 1 to test. Within test you modified the local variable x. a is not changed and can't be changed that way - we pass the value of a not a reference to a.

(defun test (x) (incf (nth 0 x))) => TEST
(setq a '(1)) => (1)
(test a) => 2
a => (2)

You pass the list (1) to test. The list is not copied. The local variable x points to the first cons cell in the list. You then modify the car of the first cons cell to 2. Since the list is not copied, you modify the passed list. a also points to the first cons cell of that list. So it is also (2).

Upvotes: 4

Jeff Foster
Jeff Foster

Reputation: 44706

See the documentation on nth. nth returns a place that setq can then operate on.

nth may be used to specify a place to setf. Specifically, (setf (nth n list) new-object) == (setf (car (nthcdr n list)) new-object)

Upvotes: 2

Related Questions