(setf (char (symbol-name nil) 1) #\U)
(Though I guess that could be taken as being the same thing as doing nonsensical pointer arithmetic in C -- you simply should know better.)"non-conforming" means you will get different results in different implementation, perhaps something like a nasal dragon, or perhaps an error signaled, or perhaps some more benign behavior.
$ clall -r '(progn (setf (char (symbol-name nil) 1) #\U) (quote nil))'
CLISP Attempt to modify a read-only string: "NIL"
ECL Detected access to an invalid or protected memory address.
Clozure Common Lisp --> #|symbol not found in home package!!|#COMMON-LISP::NUL
Armed Bear Common Lisp --> COMMON-LISP::NUL
CMU Common Lisp --> COMMON-LISP::NUL
SBCL --> COMMON-LISP::NUL
Some implementations will gladly and blissfully modify the symbol name, and your program will break because it cannot intern the original name anymore (not the best behavior for an implementation IMO); some implementation will detect the non-conforming access. Worse could have happened (remember, you are on the Internet so you can be located by geoip/gps/wifi, and missiles silos can be hacked by botnets).But otherwise indeed in general, mutable lisp objects are mutable, and you can implement mutating algorithms as well as purely functional algorithm. Foremost, you can have an hybrid approach, using what's best to solve the current problem.
The only thing I'm not fond of Racket is that compared to CL w/ Slime it feels way less interactive, a step up from Python, but still not CL (nor Smalltalk)
But lets focus on the positive, the OP is highlighting that the trite criticism of non-lispers about parens is bogus.
There's setf and setq for assigning; nconc, nsubst, and the destructive list operations; rplaca and rplacd; etc.
It's easy to write Lisp that doesn't mutate (let), or use constructs that hide it (dolist, dotimes, etc.), but mutable data has been in Lisp since the beginning.
That said, there are languages in the family that don't allows mutation, but they're a small minority.