Re: I proclaim that I really dont know where to put my declaim
- From: Kent M Pitman <pitman@xxxxxxxxxxx>
- Date: 28 Jul 2007 03:41:02 -0400
Liu Fung Sin <fungsin.lui@xxxxxxxxx> writes:
I've read some of the previous discussions regarding proclaim and
declaim ... I still don't know how to apply this in practice.
[In a setup file:]
(declaim (optimize (debug 3) (safety 3) (speed 0) (space 0)))
;;
;; If I put declaim here, will it affect the libraries that this
;; module depends on ?
;;
;; Specifically, will it affect lib1 and lib2 ?
;;
;; If not, how do I apply this optimization setting to lib1 and
;; lib2 without changing its source code?
You call PROCLAIM prior to initiating a compile action. [More on that
in the end.]
[In file2.lisp:]
(declaim (optimize (debug 3) (safety 3) (speed 0) (space 0)))
;;
;; If I declaim in package.lisp instead, will this apply to the all
;; functions that I'm going to define in package :test (again, file1,
;; file2, file3)
From http://www.lispworks.com/documentation/HyperSpec/Body/m_declai.htm#declaim
If a use of this macro appears as a top level form in a file being
processed by the file compiler, the proclamations are also made at
compile-time. As with other defining macros, it is unspecified
whether or not the compile-time side-effects of a declaim persist
after the file has been compiled.
Is there something unclear about "it is unspecified" here?
That is, the spec is not failing to say what is true, it's just that
what is true is that you don't know.
For example, saying that "it is unknown whether there is a God" is not
an ambiguous statement; it is an objectively true statement. Whether
there is a God is open to interpretation/faith/debate, so might be said
to be ambiguous. But the statement that no one knows how to resolve such
a debate involves no ambiguity.
So, too, here. The spec does not define this. That isn't ambiguous.
It merely says, as a point of fact, that you have no way of knowing
the answer portably.
In still other words, if you want it to apply to file3, and you want
to use declaim, then you should put it in file3. If you want
something else in file3, then you must make that need explicit in
file3.
Additional notes:
A package is not a file, so if the package is still getting
definitions in another file, this text is quite explicit that you
can't rely on it.
Moreover, a declaim is not "scoped" to a package. A package is a
thing about how the reader and related operations (e.g., INTERN)
work. Declarations made in a certain package will certainly affect
other packages that occur in the same file (if you switch prevailing
packages during a file). A package contains nothing more than
symbols--it does not contain environment info.
- - - - -
The issue is that compilation is done before evaluation. So if you put
(proclaim ...) in a file, it won't get executed until load time and so
will not affect compilation ... of that file. But if you call proclaim
prior to calling compile-file in the Lisp doing the compilation, it will
make a global change to that Lisp that should affect future compilations.
So if you have a file load-up.lisp that proclaims data and then makes
explicit calls to compile-file, you should be fine.
The purpose of declaim is to allow you, within a file, to compile the
file in a way that affects the compilation "in time". It does this by
making a compile-time side-effect. The scope of that effect is only
guaranteed to be to the file because there's no guarantee that a compiler
will keep the same compile-time environment across file compilations.
I'd bet most implementations will keep the same environment across a
compilation unit, so you may mostly win. But from a strict definitional
point of view, you can't rely on that. So either ask your vendors if you
can rely on it in the implementations you care about, or else make your
declarations explicit at the top of each file.
But note also that as soon as any file loads that had a declaim in it,
that file will make a global change in effect to the global state of
the Lisp which is seen at least when the next time a compilation unit
starts (unless superseded by another file that was loaded with
different settings). What's unclear is whether implementations use
some other environment than the global/runtime environment for
compilation. I think the intent was that they at least could (and
someone who's looked this up recently can say whether they are
required to--I remember there was much debate and don't remember how
it came out).
In practice, I think a lot of implementations found it hard to
separate the compilation environment from the global environment, so I
bet in most environments a proclaim being loaded during a compilation
environment affects that compilation environment immediately and
doesn't wait for you to finish the environment before making it
visible. I think it's normally too hard to make it do otherwise
unless you're doing the hack that KCL used to do of spawning an
inferior process to do a file compile in an utterly separate address
space. But it's the presence of options like that which make the
whole thing a mess.
The rule that results reminds me a little of the rule I learned for driving
in rotaries in the Boston area [that's a "roundabout" for you guys in the UK].
Around here, each rotary seems to follow its own rules of who can enter when,
notwithstanding the fact that the law requires a rule that many don't use.
The rule I learned was "Don't hit anything." ... In other words, practice
"defensive driving" by not assuming others will do their part. You can insist
on driving by the rules, but you'll probably get hit. And so the question
soon becomes "are you up to the hassle of that, or is it easier to just
go with the flow (so to speak)?"
Defensive programming in the case of declaim is to just sprinkle them in more
places than you may wish you had to, or else put a PROCLAIM before the whole
biz starts. I'd say to do the latter, since this allows you to make the change
without affecting your individual code. Either that or make a macro that is
sensitive to a compilation or runtime setting. e.g.,
(defmacro quickly (&body forms) ;unconditional
`(locally (declare (optimize (speed 3)))
,@forms))
(defmacro usually-quickly (&body forms)
(if *usually* ;compile-time test
`(quickly ,@forms)
`(progn ,@forms)))
(defmacro quickly-if (test &body forms)
`(if ,test ;runtime test
(quickly ,@forms)
(progn ,@forms)))
In general, I doubt you'll find much in the way of declaration processing
other than (SAFETY 3) that reliably works the same in all implementations,
so making macros with tighter granularity allows you to make them conditional
on implementation variation in a way that is semi-portable [in the sense that
the macro's uses are able to be portable even if the definition is not]...
(defmacro quickly (&body forms)
`(locally (declare #+some-lisp '(optimize (speed 3) (debug 1))
#-some-lisp '(optimize (speed 3)))
,@forms))
- - - - -
Disclaimer: I didn't do a big survey of what implementations are
doing. Nor have I looked seriously at this issue in a while. So
don't take what I'm saying as gospel--just as one person's experience
over a long period of time. I rarely set these things globally--I
usually only set them locally within a particular function I have
a special need to optimize, in the vague kind of style I used in the
QUICKLY macro above... though the specific conditions I made up there
are just samples.
.
- Follow-Ups:
- Re: I proclaim that I really dont know where to put my declaim
- From: Don Geddis
- Re: I proclaim that I really dont know where to put my declaim
- From: Liu Fung Sin
- Re: I proclaim that I really dont know where to put my declaim
- References:
- I proclaim that I really dont know where to put my declaim
- From: Liu Fung Sin
- I proclaim that I really dont know where to put my declaim
- Prev by Date: I proclaim that I really dont know where to put my declaim
- Next by Date: Re: (setf (getf ... and list of plists
- Previous by thread: I proclaim that I really dont know where to put my declaim
- Next by thread: Re: I proclaim that I really dont know where to put my declaim
- Index(es):
Relevant Pages
|
|