英文:
PROCLAIM has no durable effect when invoked from LOAD
问题
我正在使用SBCL。
- (proclaim '(optimize (speed 3)))
- (describe-compiler-policy)
;; 如预期所示,显示SPEED优化质量为3
然而,如果我将PROCLAIM放在一个文件中,然后LOAD它,没有任何更改:
;; 文件:"test.lisp"
(proclaim '(optimize (speed 3)))
;; 在REPL中
- (proclaim '(optimize (speed 1)))
- (load "test.lisp")
- (describe-compiler-policy)
;; 显示SPEED优化质量为1。我本来希望它为3。
为什么会这样,以及这是否有文档记录?(CLHS关于LOAD说LOAD会重置*package*和*readtable*,但没有提到声明。)
英文:
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.)
答案1
得分: 3
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 behavior in its documentation.
Why I think SBCL's behavior is sensible
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 thinksafety
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.
英文:
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.
Why I think SBCL's behaviour is sensible
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 thinksafety
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论