Why aren't lisp keywords protected?
(define a 3) (define define +) #makes define useless (define a 1) #outputs 4, instead of assigning 1 to a.
Is this flexibility so important? Or even worse:
(define + -) (+ 1 1) #Output 0.
Where can this be useful, and, can this behavior be blocked? AFAIK, all programming languages have reserved keywords.
Why aren't lisp keywords protected?
Because they aren't keywords, they are just library functions like any other.
Where can this be useful,
It means that you, as a user, have the same power as the language designer. Making a change to a language can take several decades and is a massive undertaking. Writing a new library function only takes seconds and can be done by anyone.
AFAIK, all programming languages have reserved keywords.
No, not all. Lisp doesn't, for example. In fact, Lisp doesn't really have syntax at all.
Io has no keywords, neither have Ioke or Seph. Poison and Potion also don't have keywords.
Smalltalk also has only a very small number of keywords:
thisContext. Newspeak has almost the same list (
outer). In both cases,
false could just as easily be method calls instead, leaving only 3 keywords. (Actually, Gilad Bracha, the designer of Newspeak said that all of them could be made method calls, but it wouldn't be worth it.)
Symbols are not protected because they don't need to be. Some languages have reserved names because their syntax cannot tolerate having a class named "class", even though technically you could avoid it. Sometimes it is done on purpose to avoid ambiguity in the programmer's mind and truly, redefining
- to mean
+ is the kind of things that really would be disastrous in theory. However, this is part of having a dynamic environment, where this kind of flexibility is useful sometimes.
Those problems vanish when you use different namespaces, so that
mypackage:+ is different from
yourpackage:+ (unqualified uses of
+ can be inspected during development to know which symbols is actually used).
By the way, your example is in Scheme (you tagged it as lisp originally), but Common Lisp is a little bit different in that regard.
The 978 symbols in the standardized "COMMON-LISP" package shouldn't be redefined in a portable program (undefined behavior if you do this). An implementation like SBCL provides a way to "lock" packages, to prevent accidental changes. Of course, it gives you a way to unlock them.
This is not a problem in practice because you generally don't want to redefine the standard operators but provide your own operator, defined in your own package.
Packages being first class, you can even modify which symbols are imported in a given package, so that you can sometimes change the semantics of an existing programs without touching its files, just by changing what an unqualified
+ function means (and recompiling).
This is useful, for example, to perform some kind of instrumentation, like automatic differentiation. You replace a set of operators by your own because you want to compute information about your program, for example.
In Common Lisp, all symbols in the package
COMMON LISP are protected by the standard. It says that redefining the package or the symbols in the package has undefined consequences. Which means, everything can happen: nothing, the change is made, the program crashes, the program might run into an error, ..., or even the sun comes up in the west the next morning.
Real Common Lisp implementations will often warn the user:
CL-USER 1 > (defun defun () 3) Error: Redefining function DEFUN visible from package COMMON-LISP. 1 (continue) Redefine it anyway. 2 (abort) Return to level 0. 3 Restart top-level loop.
* (defun defun () 3) debugger invoked on a SYMBOL-PACKAGE-LOCKED-ERROR: Lock on package COMMON-LISP violated when proclaiming DEFUN as a function while in package COMMON-LISP-USER. See also: The SBCL Manual, Node "Package Locks" The ANSI Standard, Section 22.214.171.124.2 Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name): 0: [CONTINUE ] Ignore the package lock. 1: [IGNORE-ALL ] Ignore all package locks in the context of this operation. 2: [UNLOCK-PACKAGE] Unlock the package. 3: [ABORT ] Exit debugger, returning to top level.
Since many Common Lisp implementations are largely programmed in themselves, there needs to be a mechanism to allow changes and then later prevent them.
Some parts of the language even can't be modified by redefining the function or macro. There is no way for the user to change, add or remove special forms (like LET) and special syntax like argument lists and lambda expressions. The syntax for argument lists is hardwired into the language. The syntax for lambda expressions is hardwired. You can't change it. You would need to change the interpreter and/or the compiler.