PROCLAIM在从LOAD中调用时没有持久效应。

huangapple go评论60阅读模式
英文:

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 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.

英文:

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 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.

huangapple
  • 本文由 发表于 2023年6月25日 18:22:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76549927.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定