From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Pascal J. Bourguignon" Newsgroups: gmane.emacs.devel Subject: Re: eval-when-compile Date: Fri, 27 Jul 2012 08:26:40 +0200 Organization: Informatimago Message-ID: <871ujxd8in.fsf@kuiper.lan.informatimago.com> References: <871ujx94qo.fsf@Rainer.invalid> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Trace: dough.gmane.org 1343370433 10495 80.91.229.3 (27 Jul 2012 06:27:13 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Fri, 27 Jul 2012 06:27:13 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Jul 27 08:27:13 2012 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Sue12-000251-Tu for ged-emacs-devel@m.gmane.org; Fri, 27 Jul 2012 08:27:13 +0200 Original-Received: from localhost ([::1]:55415 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sue12-0007qg-8z for ged-emacs-devel@m.gmane.org; Fri, 27 Jul 2012 02:27:12 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:61000) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sue0z-0007qb-L9 for emacs-devel@gnu.org; Fri, 27 Jul 2012 02:27:10 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Sue0t-0004Lr-C4 for emacs-devel@gnu.org; Fri, 27 Jul 2012 02:27:09 -0400 Original-Received: from plane.gmane.org ([80.91.229.3]:54353) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sue0t-0004LY-1g for emacs-devel@gnu.org; Fri, 27 Jul 2012 02:27:03 -0400 Original-Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1Sue0r-0001uB-D0 for emacs-devel@gnu.org; Fri, 27 Jul 2012 08:27:01 +0200 Original-Received: from 81.202.16.46.dyn.user.ono.com ([81.202.16.46]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Fri, 27 Jul 2012 08:27:01 +0200 Original-Received: from pjb by 81.202.16.46.dyn.user.ono.com with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Fri, 27 Jul 2012 08:27:01 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 145 Original-X-Complaints-To: usenet@dough.gmane.org X-Gmane-NNTP-Posting-Host: 81.202.16.46.dyn.user.ono.com Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9 033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR mV+hO/VvFAAAAABJRU5ErkJggg== X-Accept-Language: fr, es, en User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.4 (gnu/linux) Cancel-Lock: sha1:NDgxMTY4NDI1ZDYzMjMwMjRlYjIxYWVhMWZmYzI0ZWJiNjBkZjE0NA== X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 80.91.229.3 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:151900 Archived-At: Achim Gratz 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 {}.