* eval-when-compile @ 2012-07-27 5:01 Achim Gratz 2012-07-27 6:26 ` eval-when-compile Pascal J. Bourguignon 2012-08-08 21:13 ` eval-when-compile Johan Bockgård 0 siblings, 2 replies; 10+ messages in thread From: Achim Gratz @ 2012-07-27 5:01 UTC (permalink / raw) To: emacs-devel [I hope this is the correct list for asking this question.] I've been trying to use eval-when-compile to switch between alternate versions of code based on a compile-time decision. However it seems that either I don't understand the documentation or something doesn't quite work. Compiling this source file: --8<---------------cut here---------------start------------->8--- (eval-when-compile (if t (defvar unquoted-t "true") (defvar unquoted-nil "false"))) (eval-when-compile (if nil '(defvar quoted-t "true") '(defvar quoted-nil "false"))) --8<---------------cut here---------------end--------------->8--- results in an empty (except the header of course) byte-compiled file. I expected the quoted version to compile `(defvar quoted-nil "false")´ which is what that form evaluates to. When I wrap a defmacro around it and call that macro outside the eval-when-compile: --8<---------------cut here---------------start------------->8--- (eval-when-compile (defmacro ewc-macro (&rest body) (if nil '(defvar macro-t "true") '(defvar macro-nil "false")))) (ewc-macro) --8<---------------cut here---------------end--------------->8--- then I get the expected output in the byte-compiled file, but it seems there must be an easier way to do that. The eval-when-compile in this version suppresses the macro definition itself being byte-compiled of course. Regards, Achim. -- +<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+ SD adaptation for Waldorf rackAttack V1.04R1: http://Synth.Stromeko.net/Downloads.html#WaldorfSDada ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: eval-when-compile 2012-07-27 5:01 eval-when-compile Achim Gratz @ 2012-07-27 6:26 ` Pascal J. Bourguignon 2012-07-27 7:41 ` eval-when-compile PJ Weisberg 2012-07-27 17:50 ` eval-when-compile Achim Gratz 2012-08-08 21:13 ` eval-when-compile Johan Bockgård 1 sibling, 2 replies; 10+ messages in thread From: Pascal J. Bourguignon @ 2012-07-27 6:26 UTC (permalink / raw) To: emacs-devel Achim Gratz <Stromeko@nexgo.de> writes: > [I hope this is the correct list for asking this question.] > > I've been trying to use eval-when-compile to switch between alternate > versions of code based on a compile-time decision. However it seems > that either I don't understand the documentation or something doesn't > quite work. > > Compiling this source file: > > (eval-when-compile > (if t > (defvar unquoted-t "true") > (defvar unquoted-nil "false"))) > (eval-when-compile > (if nil > '(defvar quoted-t "true") > '(defvar quoted-nil "false"))) C-h f eval-when-compile RET Like `progn', but evaluates the body at compile time if you're compiling. Thus, the result of the body appears to the compiler as a quoted constant. In interpreted code, this is entirely equivalent to `progn'. What more can I add? The above source will evaluate, when you compile the file: (defvar unquoted-t "true") '(defvar quoted-nil "false") When you load the file, it won't evaluate anything. So what you've done is to define inside the compiler a variable named unquoted-t, and nothing else. Once the compiler exits, there remains nothing of that variable. > results in an empty (except the header of course) byte-compiled file. I > expected the quoted version to compile > `(defvar quoted-nil "false")´ Why? You never evaluated it, even at compilation time, much less at load time! > which is what that form evaluates to. When I wrap a defmacro around it > and call that macro outside the eval-when-compile: > > (eval-when-compile > (defmacro ewc-macro (&rest body) > (if nil > '(defvar macro-t "true") > '(defvar macro-nil "false")))) > (ewc-macro) Here, you're defining a macro at compilation time. When compiling this file, the macro is known and (ewc-macro) expands to (defvar macro-nil "false") so that's compiled into the elc file, and that's the only thing that's loaded. If you try to load the .el file directly, then the macro is not defined, and you're trying to call a function named (ewc-macro) which will fail. > then I get the expected output in the byte-compiled file, but it seems > there must be an easier way to do that. The eval-when-compile in this > version suppresses the macro definition itself being byte-compiled of > course. It's bad to restrict yourself to compilation-time. One can also load the sources directly (it's considered "run-time"). If you put this: (require 'cl) (eval-when (compile) (print '(hi compile))) (eval-when (load) (print '(hi load))) (eval-when (eval) (print '(hi run))) in a file named /tmp/time.el and then evaluate the following forms, the messages appear in *Messages*: (byte-compile-file "/tmp/time.el") (hi compile) t (load "/tmp/time.elc") (hi load) t (load "/tmp/time.el") (hi run) t So, while it's conceivable to have a big program loaded into the compiler that you don't want to load at run-time (eg. you're writing a compiler for a different language, load it, and then compile a program in this language thru a macro, and you want just the resulting lisp code of this compilation to be included in the .elc), but in general, you want to have access to the macros also at run-time (for interactive use). Now indeed, if you have decisions to make at compilation time, you need to define variables and functions at compilation time to compute those decisions. (eval-when-compile ; or (require 'cl) (eval-when (compile) … (defun decide-what-to-generate () …)) (defmacro generate-alternative () (if (decide-what-to-generate) ; called at compilation time. `(progn (defvar *first-option* 42) (defun use-first-option () (do-something-with *first-option*))) `(progn (defvar *second-option* 'zz) (defun use-second-option () (do-something-with *second-option*))))) (generate-alternative) Now of course, the problem is that when you load this file, you don't know what you will get. Will you get a function named use-first-option or a function named use-second-option? Doubt. Depends on what happened when you compiled that file… So I think it's not a good idea to do that kind of things. -- __Pascal Bourguignon__ http://www.informatimago.com/ A bad day in () is better than a good day in {}. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: eval-when-compile 2012-07-27 6:26 ` eval-when-compile Pascal J. Bourguignon @ 2012-07-27 7:41 ` PJ Weisberg 2012-07-27 8:11 ` eval-when-compile Pascal J. Bourguignon 2012-07-27 17:50 ` eval-when-compile Achim Gratz 1 sibling, 1 reply; 10+ messages in thread From: PJ Weisberg @ 2012-07-27 7:41 UTC (permalink / raw) To: Pascal J. Bourguignon; +Cc: emacs-devel On Thu, Jul 26, 2012 at 11:26 PM, Pascal J. Bourguignon <pjb@informatimago.com> wrote: > Achim Gratz <Stromeko@nexgo.de> writes: >> (eval-when-compile >> (if t >> (defvar unquoted-t "true") >> (defvar unquoted-nil "false"))) Try evaluating that block. It has side effects, of course, but the result is: 'unquoted-t That's just a symbol, sitting there all alone and not doing anything. There are no instructions to execute, so the byte compiler doesn't have anything to output. >> (eval-when-compile >> (if nil >> '(defvar quoted-t "true") >> '(defvar quoted-nil "false"))) That evaluates to: '(defvar quoted-nil "false") That's a list. Just a list, not a function call. Once again, nothing for the byte compiler to do. eval-when-compile isn't a macro; it results in a value, not code. >> (eval-when-compile >> (defmacro ewc-macro (&rest body) >> (if nil >> '(defvar macro-t "true") >> '(defvar macro-nil "false")))) >> (ewc-macro) *That's* a macro. eval-when-compile still outputs a value, but the macro call outputs code. Here, the .elc file will be the equivalent of: 'ewc-macro (defvar macro-nil "false") Line 1 is a no-op, but line 2 is just what you want. > Here, you're defining a macro at compilation time. When compiling this > file, the macro is known and (ewc-macro) expands to (defvar macro-nil > "false") so that's compiled into the elc file, and that's the only thing > that's loaded. > > If you try to load the .el file directly, then the macro is not defined, > and you're trying to call a function named (ewc-macro) which will fail. That's incorrect. Things inside the eval-when-compile get evaluated when the .el file is loaded, but not when the .elc file is loaded. It's *not* the equivalent of Common Lisp's (eval-when (compile) body...) -PJ Gehm's Corollary to Clark's Law: Any technology distinguishable from magic is insufficiently advanced. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: eval-when-compile 2012-07-27 7:41 ` eval-when-compile PJ Weisberg @ 2012-07-27 8:11 ` Pascal J. Bourguignon 0 siblings, 0 replies; 10+ messages in thread From: Pascal J. Bourguignon @ 2012-07-27 8:11 UTC (permalink / raw) To: emacs-devel PJ Weisberg <pj@irregularexpressions.net> writes: > On Thu, Jul 26, 2012 at 11:26 PM, Pascal J. Bourguignon > <pjb@informatimago.com> wrote: >> If you try to load the .el file directly, then the macro is not defined, >> and you're trying to call a function named (ewc-macro) which will fail. > > That's incorrect. Things inside the eval-when-compile get evaluated > when the .el file is loaded, but not when the .elc file is loaded. > It's *not* the equivalent of Common Lisp's (eval-when (compile) > body...) You're right, I misread C-h f eval-when-compile. Hence the importance of reading well the documentation! -- __Pascal Bourguignon__ http://www.informatimago.com/ A bad day in () is better than a good day in {}. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: eval-when-compile 2012-07-27 6:26 ` eval-when-compile Pascal J. Bourguignon 2012-07-27 7:41 ` eval-when-compile PJ Weisberg @ 2012-07-27 17:50 ` Achim Gratz 2012-07-28 0:52 ` eval-when-compile Stephen J. Turnbull 2012-07-28 18:04 ` eval-when-compile PJ Weisberg 1 sibling, 2 replies; 10+ messages in thread From: Achim Gratz @ 2012-07-27 17:50 UTC (permalink / raw) To: emacs-devel Pascal J. Bourguignon writes: > C-h f eval-when-compile RET > > Like `progn', but evaluates the body at compile time if you're compiling. > Thus, the result of the body appears to the compiler as a quoted constant. > In interpreted code, this is entirely equivalent to `progn'. > > What more can I add? I read that. It doesn't seem to work that way or has some strings attached that aren't obvious to me from the documentation. > The above source will evaluate, when you compile the file: > > (defvar unquoted-t "true") > '(defvar quoted-nil "false") No. They will evaluate to unquoted-t (defvar quoted-nil "false") The unquoted variant was only there to check if maybe there's another `(quote …)´ snuck in. I expected the defvar form to compile, but it doesn't. > When you load the file, it won't evaluate anything. Actually they will evaluate to the very same thing, per the definition of eval-when-compile. It's easy enough to see that this part is working as advertised. > Here, you're defining a macro at compilation time. When compiling this > file, the macro is known and (ewc-macro) expands to (defvar macro-nil > "false") so that's compiled into the elc file, and that's the only thing > that's loaded. Yes, that is working as expected, however I don't like the clutter that it produces. > If you try to load the .el file directly, then the macro is not defined, > and you're trying to call a function named (ewc-macro) which will fail. Again, the macro will be defined at load time and expanded from the `(ewc-macro)´ form. There'd be a lot of broken code in Emacs if that wasn't working. > Now indeed, if you have decisions to make at compilation time, you need > to define variables and functions at compilation time to compute those > decisions. What I'm actually trying to do is providing compatibility definitions for other versions of Emacs. That works fine as long as I only need to compute different values at compile time (as documented in the manual). It doesn't work when I can do a `(defalias …)´ for one version of Emacs, but need a `(defun …)´ for another. It can all be solved one way or the other by adding macros to the mix, but my question still hasn't been answered: why does it not work with eval-when-compile? Regards, Achim. -- +<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+ SD adaptation for Waldorf Blofeld V1.15B11: http://Synth.Stromeko.net/Downloads.html#WaldorfSDada ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: eval-when-compile 2012-07-27 17:50 ` eval-when-compile Achim Gratz @ 2012-07-28 0:52 ` Stephen J. Turnbull 2012-07-28 6:01 ` eval-when-compile Achim Gratz 2012-07-28 18:04 ` eval-when-compile PJ Weisberg 1 sibling, 1 reply; 10+ messages in thread From: Stephen J. Turnbull @ 2012-07-28 0:52 UTC (permalink / raw) To: Achim Gratz; +Cc: emacs-devel Achim Gratz writes: > What I'm actually trying to do is providing compatibility definitions > for other versions of Emacs. Have you looked at the techniques used in APEL? ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: eval-when-compile 2012-07-28 0:52 ` eval-when-compile Stephen J. Turnbull @ 2012-07-28 6:01 ` Achim Gratz 0 siblings, 0 replies; 10+ messages in thread From: Achim Gratz @ 2012-07-28 6:01 UTC (permalink / raw) To: emacs-devel Stephen J. Turnbull writes: > > What I'm actually trying to do is providing compatibility definitions > > for other versions of Emacs. > > Have you looked at the techniques used in APEL? As I don't even knew it existed until now: no. I#ll take a look when I find the time. Regards, Achim. -- +<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+ Factory and User Sound Singles for Waldorf Blofeld: http://Synth.Stromeko.net/Downloads.html#WaldorfSounds ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: eval-when-compile 2012-07-27 17:50 ` eval-when-compile Achim Gratz 2012-07-28 0:52 ` eval-when-compile Stephen J. Turnbull @ 2012-07-28 18:04 ` PJ Weisberg 2012-08-08 18:51 ` eval-when-compile Achim Gratz 1 sibling, 1 reply; 10+ messages in thread From: PJ Weisberg @ 2012-07-28 18:04 UTC (permalink / raw) To: Achim Gratz; +Cc: emacs-devel On Fri, Jul 27, 2012 at 10:50 AM, Achim Gratz <Stromeko@nexgo.de> wrote: > Pascal J. Bourguignon writes: >> C-h f eval-when-compile RET >> >> Like `progn', but evaluates the body at compile time if you're compiling. >> Thus, the result of the body appears to the compiler as a quoted constant. >> In interpreted code, this is entirely equivalent to `progn'. >> >> What more can I add? > > I read that. It doesn't seem to work that way or has some strings > attached that aren't obvious to me from the documentation. > >> The above source will evaluate, when you compile the file: >> >> (defvar unquoted-t "true") >> '(defvar quoted-nil "false") > > No. They will evaluate to > > unquoted-t > (defvar quoted-nil "false") > > The unquoted variant was only there to check if maybe there's another > `(quote …)´ snuck in. I expected the defvar form to compile, but it > doesn't. You missed this part: Thus, the result of the body appears to the compiler as a quoted constant. So they really evaluate to: 'unquoted-t '(defvar quoted-nil "false") Which of course does nothing, so the compiler optimizes it away. You know what you could do? --- (eval (eval-when-compile (if nil '(defvar quoted-t "true") '(defvar quoted-nil "false"))) --- That'll compile to: --- (eval '(defvar quoted-nil "false")) --- -PJ Gehm's Corollary to Clark's Law: Any technology distinguishable from magic is insufficiently advanced. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: eval-when-compile 2012-07-28 18:04 ` eval-when-compile PJ Weisberg @ 2012-08-08 18:51 ` Achim Gratz 0 siblings, 0 replies; 10+ messages in thread From: Achim Gratz @ 2012-08-08 18:51 UTC (permalink / raw) To: emacs-devel PJ Weisberg writes: > You know what you could do? > > --- > (eval > (eval-when-compile > (if nil > '(defvar quoted-t "true") > '(defvar quoted-nil "false"))) > --- > > That'll compile to: > > --- > (eval > '(defvar quoted-nil "false")) > --- Thanks. I tried this and actually it compiles to just (defvar quoted-nil "false") as I expected my first variant to do. I am not sure what the outer eval is doing, though: it doesn't look like it is executed at compile-time, so it must somehow be optimized away by the byte-compiler (some rule that "(eval (quote <…>))" is identical to "<…>", perhaps?). Regards, Achim. -- +<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+ SD adaptations for Waldorf Q V3.00R3 and Q+ V3.54R2: http://Synth.Stromeko.net/Downloads.html#WaldorfSDada ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: eval-when-compile 2012-07-27 5:01 eval-when-compile Achim Gratz 2012-07-27 6:26 ` eval-when-compile Pascal J. Bourguignon @ 2012-08-08 21:13 ` Johan Bockgård 1 sibling, 0 replies; 10+ messages in thread From: Johan Bockgård @ 2012-08-08 21:13 UTC (permalink / raw) To: emacs-devel Achim Gratz <Stromeko@nexgo.de> writes: > I've been trying to use eval-when-compile to switch between alternate > versions of code based on a compile-time decision. (if (eval-when-compile CONDITION) ...) ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2012-08-08 21:13 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-07-27 5:01 eval-when-compile Achim Gratz 2012-07-27 6:26 ` eval-when-compile Pascal J. Bourguignon 2012-07-27 7:41 ` eval-when-compile PJ Weisberg 2012-07-27 8:11 ` eval-when-compile Pascal J. Bourguignon 2012-07-27 17:50 ` eval-when-compile Achim Gratz 2012-07-28 0:52 ` eval-when-compile Stephen J. Turnbull 2012-07-28 6:01 ` eval-when-compile Achim Gratz 2012-07-28 18:04 ` eval-when-compile PJ Weisberg 2012-08-08 18:51 ` eval-when-compile Achim Gratz 2012-08-08 21:13 ` eval-when-compile Johan Bockgård
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).