I am using SBCL.
* (proclaim '(optimize (speed 3)))
* (describe-compiler-policy)
;; as expected, shows that the SPEED quality is 3
However, if I put the PROCLAIM in a file and then LOAD it, no change persists:
;; file: "test.lisp"
(proclaim '(optimize (speed 3)))
;; in REPL
* (proclaim '(optimize (speed 1)))
* (load "test.lisp")
* (describe-compiler-policy)
;; Shows that SPEED quality is 1. I would expect it to be 3.
Why is this and where is it documented? (CLHS for LOAD says that LOAD resets *package* and *readtable* but says nothing about declarations.)
I am not sure that the scope of proclaim
used like this is defined: there certainly are various cases where things like this are explicitly undefined: see 3.2.1.1.1.
However it's clear that what SBCL is doing is the useful thing I think. In particular consider a file to be compiled which begins with this:
(declaim (optimize ...))
I think it's clear that the intent of such a thing is to say "for this file, I want the compiler to listen to these optimization settings, without the need to place them at the start of each definition". It would clearly be very undesirable if a file which began with
(declaim (optimize (safety 0) ...))
caused the system to, from then on and including after the file was compiled, compile with those settings.
But (declaim (optimize ...))
is the same thing as
(eval-when (:compile-toplevel :load-toplevel :execute)
(proclaim '(optimize ...)))
In other words the proclamation happens at compile time and load time. So, if the optimization settings proclaimed by proclaim
persist after a file is loaded then a declaim
at top-level in a file can have very undesirable results.
So what SBCL is doing is the sensible thing, I think. But, once again, I do not know if this is specified anywhere: I am reasonably sure the standard does not say, but perhaps SBCL specifies this behaviour in its documentation.
This is not part of the answer.
I think it should be the case (which is a different claim than 'the standard says it is the case') that the scope of declarations made by proclaim
/ declaim
should depend on the declaration. To give three examples:
(declaim (special *foo*))
should clearly be truly global;(declaim (optimize (safety 0)))
should persist no longer than the file being loaded or the current compilation unit during compilation by default;(declaim (impl:fixnum-overflow-behaviour :execute-user-and-catch-fire))
should very, very definitely be scoped the way I think safety
should be.Not doing this just makes it really laborious to write programs: every file of every program needs to specify all the declarations it cares about including implementation-specific ones, and can hot assume any sane default value, since the values may have been set to some mad thing by any previous file that was compiled or loaded. That would be ... painful.