Question

I'm noticing some inconsistency in the output of this code in Clisp:

(defvar str "Another")
(setf (char str 3) #\!)

When I run it from the repl, I get the desired result:

[1]> (defvar str "Another")
STR
[2]> (setf (char str 3) #\!)
#\!
[3]> str
"Ano!her"
[4]>

However, when I run it from a script, I get a warning about modifying a readonly string:

*** - Attempt to modify a read-only string: "Another"

I got that error when running this code:

(print (do ((str "foobar")
            (i 0 (+ i 1)))
           ((= i (length str)) str)
         (setf (char str i) #\!)))

What's the point of making the string read-only(I'm assuming this is the same as immutable) when the binding will dissappear when the block ends?

And, why the discrepancy between the two outputs?

Lastly, is there a way to turn it off? I don't find the warning particularly useful.

Was it helpful?

Solution

Solution

First of all, what you are seeing is an error, not a warning.

Second, you cannot turn it off, but you can avoid it by copying the immutable string:

(print (do ((str (copy-seq "foobar"))
            (i 0 (+ i 1)))
           ((= i (length str)) str)
         (setf (char str i) #\!)))

Motivation

Why some data is made immutable is a topic much discussed on the web.

The basic reasons are:

  • safety in a multithreaded environment and
  • better compilers

Justification

As per the manual:

An attempt to modify read-only data SIGNALs an ERROR. Program text and quoted constants loaded from files are considered read-only data. This check is only performed for strings, not for conses, other kinds of arrays, and user-defined data types.

This is explicitly permitted by the ANSI CL spec:

implementations are not required to detect attempts to modify immutable objects or cells; the consequences of attempting to make such modification are undefined

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top