From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.devel Subject: Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp? Date: Sat, 2 Sep 2023 15:06:46 +0000 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="24072"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org, Mattias =?iso-8859-1?Q?Engdeg=E5rd?= To: Stefan Kangas Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat Sep 02 17:08:00 2023 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qcSEB-00063l-LL for ged-emacs-devel@m.gmane-mx.org; Sat, 02 Sep 2023 17:07:59 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qcSDO-0005fL-PT; Sat, 02 Sep 2023 11:07:10 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qcSDL-0005et-3m for emacs-devel@gnu.org; Sat, 02 Sep 2023 11:07:08 -0400 Original-Received: from mail.muc.de ([193.149.48.3]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qcSDI-0003uP-0w for emacs-devel@gnu.org; Sat, 02 Sep 2023 11:07:06 -0400 Original-Received: (qmail 464 invoked by uid 3782); 2 Sep 2023 17:06:48 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=muc.de; i=@muc.de; q=dns/txt; s=default; t=1693667207; h=date : to : cc : subject : message-id : references : mime-version : content-type : in-reply-to : from : from; bh=YCTGn6Z7BKvwHwhyO0EbpF20KTzaqnlHJwWW4Jvk3bw=; b=OrlXNfF87V9JPwkOFmEg4cSeEUi5Im4bmx5Jyes6aM+7mS2jdo/9o2KGhZYZJDaBI2rSt lwBqlBJIb8C0d/Dw36qLHHeGE44fgeSTVFuPR+xYdk7mQWM6jLNTWn5vouaH4WtbWyURiKy aonOP2W0ae2uRskjpsPMDI08xaQh5DCvk117TlBueaBNO9ipq+077Om4na805vjqy9oZkIN xiHOi2BREFc7vByy8QJ5dyM6VLKOs50iXHHpDGc51SVF2qpeg/UANVObuzH3XCnfqLwXtzA Rjckz2n9sRuOSWbaOXdWcYlJ98rxkyb8LzH1UTIjCfw0pzGxW2FDfsVPA4pQ== Original-Received: from acm.muc.de (p4fe15929.dip0.t-ipconnect.de [79.225.89.41]) (using STARTTLS) by colin.muc.de (tmda-ofmipd) with ESMTP; Sat, 02 Sep 2023 17:06:46 +0200 Original-Received: (qmail 29831 invoked by uid 1000); 2 Sep 2023 15:06:46 -0000 Content-Disposition: inline In-Reply-To: X-Submission-Agent: TMDA/1.3.x (Ph3nix) X-Primary-Address: acm@muc.de Received-SPF: pass client-ip=193.149.48.3; envelope-from=acm@muc.de; helo=mail.muc.de X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 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-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:309895 Archived-At: Hello, Stefan. On Wed, Aug 30, 2023 at 20:17:48 +0200, Stefan Kangas wrote: > Alan Mackenzie writes: > > I looked at APEL, and its code was near identical to what I (with help > > from PK) wrote. I'd have nothing against the name static-if instead. > > As long as this doesn't raise copyright assignment problems, assuming > > the authors of APEL haven't assigned copyright to the FSF. > I think it's fine as far as copyright goes. You came up with your > version independently, before even looking at their code. We even > have a public record of that right here on this list. IANAL, but the > name `static-if' in itself is also not copyrightable, AFAIU. OK, static-if it is. I think the code and documentation are ready to be committed. For anybody who wants one last check, here's the intended patch: diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi index 3aee9dd80e4..41e5cb148e5 100644 --- a/doc/lispref/control.texi +++ b/doc/lispref/control.texi @@ -36,13 +36,14 @@ Control Structures structure constructs (@pxref{Macros}). @menu -* Sequencing:: Evaluation in textual order. -* Conditionals:: @code{if}, @code{cond}, @code{when}, @code{unless}. -* Combining Conditions:: @code{and}, @code{or}, @code{not}, and friends. +* Sequencing:: Evaluation in textual order. +* Conditionals:: @code{if}, @code{cond}, @code{when}, @code{unless}. +* Combining Conditions:: @code{and}, @code{or}, @code{not}, and friends. * Pattern-Matching Conditional:: How to use @code{pcase} and friends. -* Iteration:: @code{while} loops. -* Generators:: Generic sequences and coroutines. -* Nonlocal Exits:: Jumping out of a sequence. +* Iteration:: @code{while} loops. +* Generators:: Generic sequences and coroutines. +* Nonlocal Exits:: Jumping out of a sequence. +* Conditional Compilation:: A facility like C's #if. @end menu @node Sequencing @@ -2467,3 +2468,48 @@ Cleanups @code{ftp-setup-buffer} returns but before the variable @code{process} is set, the process will not be killed. There is no easy way to fix this bug, but at least it is very unlikely. + +@node Conditional Compilation +@section Conditional Compilation + + There will be times when you want certain code to be compiled only +when a certain condition holds. This is particularly the case when +maintaining Emacs packages; to keep the package compatible with older +versions of Emacs you may need to use a function or variable which has +become obsolete in the current version of Emacs. + + You could just use a conditional form to select the old or new form +at run time, but this tends to output annoying warning messages about +the obsolete function/variable. For such situations, the macro +@code{static-if} comes in handy. It is inspired by the conditional +compilation directives like @code{#if} in C like languages, and is +patterned after the special form @code{if} (@pxref{Conditionals}). + + To use this facility for an older version of Emacs, copy the source +for @code{static-if} from the Emacs source file @file{lisp/subr.el} +into your package. + +@defmac static-if condition then-form else-forms... +Test @var{condition} at macro-expansion time. If its value is +non-@code{nil}, expand the macro to @var{then-form}, otherwise expand +it to @var{else-forms} enclosed in a @code{progn}. @var{else-forms} +may be empty. + +Here is an example of its use from CC Mode, which prevents a +@code{defadvice} form being compiled in newer versions of Emacs: +@example +@group +(static-if (boundp 'comment-line-break-function) + (progn) + (defvar c-inside-line-break-advice nil) + (defadvice indent-new-comment-line (around c-line-break-advice + activate preactivate) + "Call `c-indent-new-comment-line' if in CC Mode." + (if (or c-inside-line-break-advice + (not c-buffer-is-cc-mode)) + ad-do-it + (let ((c-inside-line-break-advice t)) + (c-indent-new-comment-line (ad-get-arg 0)))))) +@end group +@end example +@end defmac diff --git a/etc/NEWS b/etc/NEWS index 5c11b6b9ac7..4e7e185c8bc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -855,6 +855,10 @@ Use 'define-minor-mode' and 'define-globalized-minor-mode' instead. See the "(elisp) Porting Old Advice" node for help converting them to use 'advice-add' or 'define-advice' instead. ++++ +** There is now conditional compilation, based on the C language's #if. +To use this, see the new macro 'static-if'. + +++ ** Desktop notifications are now supported on the Haiku operating system. The new function 'haiku-notifications-notify' provides a subset of the diff --git a/lisp/subr.el b/lisp/subr.el index 47fcbc2f317..1a7d8aadd46 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -277,6 +277,23 @@ pop (macroexp-let2 macroexp-copyable-p x getter `(prog1 ,x ,(funcall setter `(cdr ,x)))))))) +;; Note: `static-if' handles the version of `eval' without the &optional +;; parameter LEXICAL so that it can be copied unchanged for use in older +;; Emacsen. +(defmacro static-if (condition then-form &rest else-forms) + "A conditional compilation macro analogous to C's #if. +Evaluate CONDITION at macro-expansion time. If it is non-nil, +expand the macro to THEN-FORM. Otherwise expand it to ELSE-FORMS +enclosed in a `progn' form. ELSE-FORMS may be empty." + (declare (indent 2) + (debug (sexp sexp &rest sexp))) + (if (condition-case err + (eval condition lexical-binding) + ((wrong-number-of-arguments void-variable) (eval condition)) + ((debug error) (signal (car err) (cdr err)))) + then-form + (cons 'progn else-forms))) + (defmacro when (cond &rest body) "If COND yields non-nil, do BODY, else return nil. When COND yields non-nil, eval BODY forms sequentially and return -- Alan Mackenzie (Nuremberg, Germany).