I'm trying to make sbcl case sensitive with no success. Does anyone know what the problem might be? It mentions here and here that is possible.
I'm running
(setf (readtable-case *readtable*) :invert)
(defun hi () "Hi!")
(HI)
(HI)
"Hi!"
Inside of the repl like the following.
"C:\Program Files\Steel Bank Common Lisp\1.2.15\sbcl.exe" --core "C:\Program Files\Steel Bank Common Lisp\1.2.15\sbcl.core"
EDIT: So it appears if you call a function with out case sensitivity in Common Lisp it reverts back to its old behavior of being in case sensitive for the rest of the program I have found no way of preventing this currently.
; in: Hi2
; (|Hi2|)
;
; caught style-warning:
; undefined function: Hi2
;
; compilation unit finished
; Undefined function:
; Hi2
; caught 1 STYLE-WARNING condition
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002C77BE3}>:
The function COMMON-LISP-USER::|Hi2| is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
Common Lisp is always case-sensitive. Symbols have names, which are simply strings. However, there are few things that make things seem sort of case-insensitive. To grasp what these are, you need to know a little bit about how the system reads code.
When the system reads a form, it has to create a Lisp object from the textual representation. E.g., if the reader is reading from a string like: (hello world)
, then the result should be a list of two symbols. What are the names of those symbols? That's where there's some flexibility in the reader. The default behavior is for the reader to upcase the names that are read from the input. The reader gets the input "hello" and "world", then upcases these to "HELLO" and "WORLD", and then interns those. This is controlled by the readtable case, as you've discovered. There are a few different possibilities, viz., :upcase, :downcase, :preserve, and :invert. :Preserve and :invert can be handy for interoperability code.
There's no sense in which a function has case-sensitivity or doesn't. The readtable case only affects how the reader turns the textual input into symbol names. It sounds like what you want to do is ensure that the readtable-case is :preserve or :invert when you're reading your code. Note that if the readtable-case is :invert, then all-lower-case names get upcased, all-upper-case names get downcased, and everything else is preserved. I point this out because in your example (defun hi () "Hi!"), the text "hi" will be upcased, and the symbol on which you're defining a function will have the name "HI". Then, when you write (HI), the reader will generate a list of a symbol named "hi", which can't be the same symbol.
The code provided so far doesn't work the way your example shows it working, and it doesn't look like a copy-and-paste REPL transcript. Here's what I see (and expect) when I run the code you showed:
* (setf (readtable-case *readtable*) :invert)
:invert
* (defun hi () "hello")
hi
Writing (hi) works, because the reader still inverts and gives you a symbol named "HI", as expected:
* (hi)
"hello"
But writing (HI) doesn't, because the reader inverts and gives you a symbol named "hi", as expected:
* (HI)
; in: HI
; (|hi|)
;
; caught style-warning:
; undefined function: HI
;
; compilation unit finished
; Undefined function:
; HI
; caught 1 STYLE-WARNING condition
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002FDE7D3}>:
The function COMMON-LISP-USER::|hi| is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
("undefined function")
Now, in testing this interactively, you do need to be clear about whether you're getting stuck in the debugger, because some settings (like readtable-case) may be changed within the debugger for the sake of convenience. E.g.,
* (setf (readtable-case *readtable*) :invert)
:invert
* (defun hi () "hello")
hi
* (HI)
; in: HI
; (|hi|)
;
; caught style-warning:
; undefined function: HI
;
; compilation unit finished
; Undefined function:
; HI
; caught 1 STYLE-WARNING condition
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002FDE7D3}>:
The function COMMON-LISP-USER::|hi| is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
("undefined function")
0] TOP
We entered TOP to get out of the debugger. You can enter ? to get a list of available commands. Now that we're back to the top level REPL, we can see that (HI) will have the same result. This time, we'll try executing (HI) from within the debugger, too:
* (HI)
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002FDE7D3}>:
The function COMMON-LISP-USER::|hi| is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SYMBOL-FUNCTION |hi|)
0] (HI) ;; within the debugger
"hello" ;; "HI" must have been read as "HI", not "hi"
0] TOP
From within the debuger, (HI) worked just fine. It must be resetting back to some "standard" values to make life easier for programmers. After entering TOP, though, we're back to the REPL, and (HI) will fail again:
* (HI)
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {1002FDE7D3}>:
The function COMMON-LISP-USER::|hi| is undefined.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SYMBOL-FUNCTION |hi|)
0]