This is a read-only archive of lispforum.com. The forum was locked to new users and posts and is preserved here as static HTML from a database snapshot taken on 2019-09-07.

Destructive function on constant data

8 posts · 2246 views

Can anyone tell me what I'm doing wrong here:
(let* ((x '(1 2 3 4 5))
		(y))
	   
	   (setf y (nreverse x)))
I just want to set one variable as the reverse list of the other but i get the following error:

; in: LAMBDA NIL
; (NREVERSE X)
;
; caught WARNING:
; Destructive function NREVERSE called on constant data.

:?

Re: Destructive function on constant data

Some versions of lisp don't allow you to destructively modify what it considers constant data when you use a quote.
Try this instead:
(let ((x (list 1 2 3 4 5))
       y)
  (setf y (nreverse x))
  (values y x))

Re: Destructive function on constant data

Hey thanks for the reply. Yep your code works fine. As does this i found out:
(let* ((x '(1 2 3 4 5))
		(y))
	   (setf y (reverse x)))
Which indicates the issue lies with the nreverse function?

Re: Destructive function on constant data

It's a combination of quote and nreverse. Nreverse tries to destructively change x in some versions of lisp, but it cannot because the quote makes x constant. On the other hand, 'reverse' makes a copy of x and doesn't try to change x, so no error.

Re: Destructive function on constant data

Sweet. Thanks for the clarification! :D

Re: Destructive function on constant data

BIOS wrote:Can anyone tell me what I'm doing wrong here:
(let* ((x '(1 2 3 4 5))
		(y))
	   
	   (setf y (nreverse x)))
This smells like C-style thinking. Why not this?
(let* ((x '(1 2 3 4 5))
		(y (reverse x)))
You'd actually need let* in this case, whereas let is sufficient in your original snippet, where it doesn't matter which order the bindings for x and y are evaluated.

Re: Destructive function on constant data

Afaik QUOTE does not make x constant, quote make the variable x point to a list '(1 2 3 4 5), but that list is *not* created when you call it, it is always there. So if you do:
(defun quote-abuse ()
  (let ((list '(1 2 3 4 5)))
    list))

(setf (car (quote-abuse)) 'unexpected)

(quote-abuse) ;=> (unexpected 2 3 4 5)
I guess the effect is that one should treat it as a constant,(which why it warns) but it isn't really.

Re: Destructive function on constant data

For some odd reason, I love comparing CL to C.

In C, the expression char *x="some string"; doesn't inherently mean that "some string" is a constant. However, there are efficiency gains from making it so; and string literals are now constant by mandate/standardization. (Modifying a string literal invokes "undefined behavior" -- meaning don't do that. Some compilers put them in read-only memory; thus a write will cause a memory fault.)

Same thing goes for quoted list literals in CL.