Re: (eval-when?)



Artem Baguinski <artm@xxxxx> writes:

> Dear Lispniks
>
> I am a bit confused about compile/load/execute time evaluation.
>
> Say, I have a package and i have some constants defined there with
> (defconstant ...)
>
> If now I issue M-x slime-compile-and-load-file command I get warnings
> about the constants being redefined (and even am thrown in a
> debugger).
>
> I gather it's because when I compiled the file the defconstant forms
> where already evealuated and when the lisp loads the file it has to
> evaluate them again. but I don't understand why it happens like
> that. I thought compiling file just creates the compiled version of my
> .lisp file?

That's true. But slime-compile-and-load-file, not suprisingly also
loads the file.

> on the other hand, i also used a loop to generate some of the
> constants and give them values, something like:
>
> (do ((n 0 (+ 1 n))
> (note-list '((B# C) (C# Db) (D)
> (D# Eb) (E Fb) (E# F)
> (F# Gb) (G) (G# Ab)
> (A) (A# Bb) (B Cb)) (rest note-list)))
> ((null note-list) nil)
> (mapc #'(lambda (alias)
> (eval `(defconstant ,alias ,n)))
> (car note-list)))
>
> and other code depends on the generated constants:
>
> (defconstant +standard-tuning+
> (list E B G D A E)

So this is asking for undefined behavior since if you evaluate this
form twice the (list ...) form will evaluate to two different,
i.e. non EQL, values. I'd probably use DEFPARAMETER for this.

> Now I can't compile the file because on compile time the constants E
> B G ... aren't generated yet. I feel like I have to use eval-when
> form but i don't really understand the rules. Also my constant
> generation uses eval form and I keep hearing that it's something to
> avoid.
>
> Where can I read an explanation about these different "situation"
> (compile time, load time, execute) and how to use eval-when? Something
> more newbie friendly then HyperSpec (which works for me in most cases,
> but not always).

I like to think the explanation in the section EVAL-WHEN in

<http://www.gigamonkeys.com/book/the-special-operators.html>

is pretty understandable. But I don't think EVAL-WHEN is really the
solution to this particular problem.

> Or feel free to say: all that you're doing is wrong and you have to do
> it like this (or like that).

Okay. I'd do it something like this:

(defmacro define-notes ((start) &body names)
`(progn
,@(loop for names in names
for i from start nconc
(loop for n in names collect `(defconstant ,n ,i)))))

(define-notes (0)
(B# C) (C# Db) (D) (D# Eb) (E Fb) (E# F) (F# Gb) (G) (G# Ab) (A) (A# Bb) (B Cb))

You may still get warnings about redefining constants if you eval the
DEFINE-NOTES form and then later compile and load the whole file. But
if you do you can ignore them since the values of your constants are
in fact the same (i.e. EQL). Certainly you should not end up in the
debugger.

-Peter

--
Peter Seibel * peter@xxxxxxxxxxxxxxx
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp * http://www.gigamonkeys.com/book/
.



Relevant Pages

  • Re: creaping coupling......
    ... In C++ it would be trivial to break that source code dependency, ... When you compile a .java module, ... In Java and C# it's asserted at compile time. ...
    (comp.object)
  • Re: VB Compiler Warnings & other woes ...
    ... you will get this warning in vs 2005. ... > have a direct legacy language path of evolution to consider. ... >> compile time errors rather than runtime. ...
    (microsoft.public.dotnet.languages.vb)
  • Re: No exceptions?
    ... time that was removed before runtime; there's no way to generate a compile time exception for the unexceptionable, but there are not many ways of avoiding a runtime exception if the compile time y had defined attributes. ... Thus, as soon as one compiles a statement that references any such resource, one would get a compile-time error. ... I think many products go to elaborate lengths and introduce arbitrary concepts to handle such cases, at least some of them try to prevent catalogue updates in a transaction (Jim Gray described a logical '2-phase' protocol for intension locks many years ago and I've seen it implemented and I've seen the complications that seem never to end due to the intricacy, for example a reversal of Jonathan's converse problem, a sequential transaction that references y and then deletes y's definition - what should happen if the reference is then referred to again? ...
    (comp.databases.theory)
  • Re: apparently undefined function called by macro
    ... However, as almost always in Common Lisp;), there are exceptions to this rules: Some top-level forms do indeed have effects at compile time. ... The reason is that you typically want to base subsequent code on your macro definitions, and the compiler must be able to completely macro-expand away these macro definitions as well. ... A system definition allows you to declare that one file of lisp code depends on some other file of lisp code. ...
    (comp.lang.lisp)
  • Re: RAD vs. performance
    ... iterable object--whether or not the object is an array or list is ... return ret ... known at compile time. ...
    (comp.lang.misc)