dear list,
i know that this is a subject that has strong feelings attached to, but with recent developments in XCVB the need for (eval-when (:compile-toplevel :load-toplevel :execute) ...) has rose, and seeing numerous eval-when noise in the code is potentially annoying.
related material:
a) relevant part of XCVB docs: http://common-lisp.net/project/xcvb/doc/README.html#compile-time-side-effect...
b) "XCVB patch for Alexandria" thread on alexandria-devel
c) blog entry from Nikodemus at http://random-state.net/log/3387124996.html (broken currently, google cache below)
http://209.85.129.132/search?q=cache:dmgWWKN8vFMJ:random-state.net/log/33871...
=============
c) makes it clear that Nikodemus doesn't like eval-always, and i'm sure many other lispers are on the same opinion. for the argument that it does not introduce a new abstraction, i can point to COND, which is the same as an ugly IF ladder, still most people prefer COND when there are many legs of that if, because in that case COND is much less noisy. no new abstraction, only a syntactic sugar, but it's much easier for the eye.
a) has a detailed description why often a full (:compile-toplevel :load-toplevel :execute) is necessary, and it'll be even more so as XCVB gets used more and more.
so, i'd suggest to take some action:
I) add an eval-always to alexandria-devel II) add a defun-always to alexandria-devel avoid the entire need for a wrapper III) ?
my vote goes for II), which is kinda in sync with c) too.
suggestions? opinions?
On Oct 16, 2009, at 09:50 , Attila Lendvai wrote:
I) add an eval-always to alexandria-devel II) add a defun-always to alexandria-devel avoid the entire need for a wrapper
III) ?
Don't add any of these kludges, and instead reorganize code such that EVAL-WHEN is not sprinkled throughout the code.
E.g., all code that's needed in the compilation stage goes into files separate from run-time code, with only one EVAL-WHEN per file. This has the additional advantage that one can easily test whether the stages are properly separated by just loading the "compilation stage" files. IOW, let's pretend CL had proper stage separation.
Michael Weber michaelw+alexandria@foldr.org writes:
On Oct 16, 2009, at 09:50 , Attila Lendvai wrote:
I) add an eval-always to alexandria-devel II) add a defun-always to alexandria-devel avoid the entire need for a wrapper
III) ?
Don't add any of these kludges, and instead reorganize code such that EVAL-WHEN is not sprinkled throughout the code.
E.g., all code that's needed in the compilation stage goes into files separate from run-time code, with only one EVAL-WHEN per file.
You don't even neeed EVAL-WHEN in that case; just specify that "compilation stage" files must be loaded before compiling the other respective files.
-T.
Don't add any of these kludges, and instead reorganize code such that EVAL-WHEN is not sprinkled throughout the code.
IOW, you propose that the current way of categorizing definitions into separate files should be changed so that it is based on evaluation stages.
this is certainly a cleaner solution in some ways, but it also means that for example if an ensure-car is used in a macro in the same module, then it must be moved from lists.lisp to compile-time-stage.lisp.
i would even be ok with that, but it's not any less kludgy from another point of view.
i still think that the least intruding solution in the current setup would be defun-always, but it's a strong point that then one needs a whole set of new foo-always, which is bad enough to make me indecisive.
: Michael Weber michaelw+alexandria@foldr.org Don't add any of these kludges, and instead reorganize code such that EVAL-WHEN is not sprinkled throughout the code.
: Attila Lendvai attila.lendvai@gmail.com IOW, you propose that the current way of categorizing definitions into separate files should be changed so that it is based on evaluation stages.
this is certainly a cleaner solution in some ways, but it also means that for example if an ensure-car is used in a macro in the same module, then it must be moved from lists.lisp to compile-time-stage.lisp.
i would even be ok with that, but it's not any less kludgy from another point of view.
It would be extraordinarily kludgy, especially for functions that are just MEANT to be used by macros. Why require them to be in a different file from the macros that use them, or cause the file in which they are to be loaded in a special way? That a macro uses a defun instead of an flet should be an implementation issue not exposed to the users of the macro, who shouldn't have to know that "hey, for this file, we should use the FASL, not the CFASL", just because of how the author (failed to) organize the internals of his files.
Even assuming only FASLs and not CFASLs, the constraint of segregating functions by stages is extremely cumbersome -- all the more when a function suddenly gets "promoted". Instead of being wrapped in an EVAL-WHEN, it has to be shipped to another file that maybe has to be created just for this purpose? Ouch.
The standard just doesn't guarantee that a function not in (the equivalent of) EVAL-ALWAYS will be available for use by macros, whether while compiling the same file or at any time in the future. Get over it, and please stop relying on assumptions that might be valid with how ASDF currently works, but that should really not be taken for granted -- and I can definitely envision a case where ASDF's COMPILE-OP and/or POIU's PARALLEL-COMPILE-OP would in the future use CFASLs where available.
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ] Perhaps those of us who care about quality programs have not spoken up often enough -- `for bad programs to triumph requires only that good programmers remain silent.' I call this passivity the `Silence of the Lambdas.' -- hbaker
On Oct 16, 2009, at 12:30 , Faré wrote:
: Michael Weber michaelw+alexandria@foldr.org Don't add any of these kludges, and instead reorganize code such that EVAL-WHEN is not sprinkled throughout the code.
: Attila Lendvai attila.lendvai@gmail.com IOW, you propose that the current way of categorizing definitions into separate files should be changed so that it is based on evaluation stages.
this is certainly a cleaner solution in some ways, but it also means that for example if an ensure-car is used in a macro in the same module, then it must be moved from lists.lisp to compile-time-stage.lisp.
i would even be ok with that, but it's not any less kludgy from another point of view.
It would be extraordinarily kludgy, especially for functions that are just MEANT to be used by macros. Why require them to be in a different file from the macros that use them, or cause the file in which they are to be loaded in a special way? That a macro uses a defun instead of an flet should be an implementation issue not exposed to the users of the macro, who shouldn't have to know that "hey, for this file, we should use the FASL, not the CFASL", just because of how the author (failed to) organize the internals of his files.
Fare,
I think some meaning got lost in Attila's snipping/interpreting of what I said.
I proposed phase segregation (basically because things get hairy down the line when not thinking about that from the start) based on files. However, I ALSO said that code should be wrapped in EVAL-WHEN:
all code that's needed in the compilation stage goes into files separate from run-time code, with only one EVAL-WHEN per file.
As for Attila's ENSURE-CAR use case, I see at least two options:
1. duplicate the code of small utility functions for the compilation stage. I don't really see this as a big problem, as code used in macro processing/s-expression frobbing is not likely to pull in significant code bases, say, a webserver/http-client, etc.. It also avoids pulling all the other lists.lisp stuff if that is not needed.
2. if more of lists.lisp (or other modules) would be used in "foo- macros.lisp", there must be a way to have the latter file depend on the former for the compilation stage. Otherwise, how would you solve this for xcvb now?
(FWIW, there are Scheme module systems which enforce phase separation; ObReference: Matthew Flatt, Composable and Compilable Macros, <http://www.cs.utah.edu/plt/publications/macromod.pdf
)
2009/10/16 Michael Weber michaelw+alexandria@foldr.org:
I proposed phase segregation (basically because things get hairy down the line when not thinking about that from the start) based on files. However, I ALSO said that code should be wrapped in EVAL-WHEN:
Oh, OK.
So we'd have files like foo-syntax.lisp with all the macros, eval-when'ed definitions, special declarations, and foo.lisp with the normal runtime definitions?
That's a style I think would be great to push in the CL community. We could even have slightly separate builds for "my-system-syntax" and "my-system" so that you only need "my-system-syntax" to compile stuff that is linked at runtime against "my-system". That would minimize the need for recompilation.
Otherwise, how would you solve this for xcvb now?
Either 1- Plenty of EVAL-WHEN, or 2- explicit compile-time dependency with :compile-depends-on and/or :cload-depends-on.
Note that the ASDF to XCVB converter doesn't know about :compile-depends-on, only about the simpler :depends-on.
(FWIW, there are Scheme module systems which enforce phase separation; ObReference: Matthew Flatt, Composable and Compilable Macros, http://www.cs.utah.edu/plt/publications/macromod.pdf )
Yup.
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ] The rule is, jam to-morrow and jam yesterday, but never jam today. -- Lewis Carroll
From: Attila Lendvai attila.lendvai@gmail.com
[snip]
c) makes it clear that Nikodemus doesn't like eval-always, and i'm sure many other lispers are on the same opinion. for the argument that it does not introduce a new abstraction, i can point to COND, which is the same as an ugly IF ladder, still most people prefer COND when there are many legs of that if, because in that case COND is much less noisy. no new abstraction, only a syntactic sugar, but it's much easier for the eye.
a) has a detailed description why often a full (:compile-toplevel :load-toplevel :execute) is necessary, and it'll be even more so as XCVB gets used more and more.
so, i'd suggest to take some action:
I) add an eval-always to alexandria-devel II) add a defun-always to alexandria-devel avoid the entire need for a wrapper
No, not the entire need, unless you choose to avoid compile-time use of all other CL's features.
I.e. if we're to choose a /consistent/ approach, we would be actually talking about a much wider set of *-always functions.
III) ?
my vote goes for II), which is kinda in sync with c) too.
regards, Samium Gromoff -- _deepfire-at-feelingofgreen.ru O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
Attila Lendvai wrote:
i know that this is a subject that has strong feelings attached to, but with recent developments in XCVB the need for (eval-when (:compile-toplevel :load-toplevel :execute) ...) has rose, and seeing numerous eval-when noise in the code is potentially annoying.
Potentially, yes. That's why I didn't propose to consider EVAL-ALWAYS in this discussion.
But since you bring it up, my opinion is that EVAL-ALWAYS is a simple construct that every Lisper should be able to understand without macroexpanding. Assuming it doesn't do funny things, of course.*
Not so with DEFUN-ALWAYS, though. It's not as general (you might want to define a variable at compile-time, for example) and it isn't really obvious what this does to DEFUN, since the connection to EVAL-WHEN is lost.
So I would be mildly in favor of EVAL-ALWAYS but strongly object to DEFUN-ALWAYS.
Leslie
-- * I do get Nikodemus' point that it's another piece you need to consider when debugging code that uses it, but the point quickly seems moot once EVAL-ALWAYS has settled into one's mind.
I retain most of my objections to EVAL-ALWAYS (specifically the need to consider which phases you need and why), but if my understanding of the way XCVB introduces more cases where it is needed is mostly-correct, I think I can live with it in Alexandria. DEFUN-ALWAYS I'm much more skeptical about.
My assumption of XCBV needs here is that simple XCVBification of a system introduces new cases where EVAL-WHEN is needed, and :cload-depends-on &co are possibly a hammer too big. If these dependencies are always a sufficient tool, then I'm not so sure it is really needed.
In either case, I'm not going to cry out against it very hard. DEFCLASS* I still take a firm stand on. :)
(I do agree foo-syntax.lisp and foo.lisp (or early-foo.lisp and foo.lisp -- whatever) style has much to recommend itself.)
Cheers,
-- Nikodemus
(I do agree foo-syntax.lisp and foo.lisp (or early-foo.lisp and foo.lisp -- whatever) style has much to recommend itself.)
ok, i seem to read out an agreement from the last few mails... so, how about this:
- where required, split files to foo.lisp, foo-early.lisp and use :compile-depends on. - in lack of further feedback i'll push these changes in a week or two
2009/10/28 Attila Lendvai attila.lendvai@gmail.com:
ok, i seem to read out an agreement from the last few mails... so, how about this:
- where required, split files to foo.lisp, foo-early.lisp and use
:compile-depends on.
- in lack of further feedback i'll push these changes in a week or two
I'm glad there is an agreement around the foo-early.lisp style.
Further style questions: * should such files also include (forward) declaration of function types? of variable specialness w/o variable definition? * should these files be organized in a system alexandria-early.asd or be kept in alexandria.asd?
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ] If it's not worth doing right, it's not worth doing. -- Scott McKay
2009/10/28 Faré fahree@gmail.com:
Further style questions:
- should such files also include (forward) declaration of function
types? of variable specialness w/o variable definition?
As long as DECLAIM is used instead of PROCLAIM, I don't immediately see why they should.
- should these files be organized in a system alexandria-early.asd or
be kept in alexandria.asd?
The latter, IMO.
Cheers,
-- Nikodemus
alexandria-devel@common-lisp.net