all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Alan Mackenzie <acm@muc.de>
To: Stefan Kangas <stefankangas@gmail.com>
Cc: emacs-devel@gnu.org, "Mattias Engdegård" <mattiase@acm.org>
Subject: Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
Date: Sat, 2 Sep 2023 15:06:46 +0000	[thread overview]
Message-ID: <ZPNPhh_My1P6k0vw@ACM> (raw)
In-Reply-To: <CADwFkm=jo2UtNwdTwSm71_=05pdYOejGv1WKUsx5XeDdDag=Vg@mail.gmail.com>

Hello, Stefan.

On Wed, Aug 30, 2023 at 20:17:48 +0200, Stefan Kangas wrote:
> Alan Mackenzie <acm@muc.de> 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).



  reply	other threads:[~2023-09-02 15:06 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-28 19:37 Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp? Alan Mackenzie
2023-08-28 19:47 ` Ulrich Mueller
2023-08-28 20:06   ` Alan Mackenzie
2023-08-28 21:01     ` Ulrich Mueller
2023-08-28 21:46       ` Alan Mackenzie
2023-08-31  2:07         ` Richard Stallman
2023-08-31  7:50           ` Alan Mackenzie
2023-09-04  1:34             ` Richard Stallman
2023-09-04 10:50               ` Alan Mackenzie
2023-09-04 11:02                 ` tomas
2023-09-04 15:19                   ` Emanuel Berg
2023-09-04 18:57                     ` tomas
2023-09-06  0:58                   ` Richard Stallman
2023-09-06  0:58                 ` Richard Stallman
2023-09-06  7:28                   ` Andreas Schwab
2023-09-06  9:31                     ` Alan Mackenzie
2023-09-06  9:56                   ` Alan Mackenzie
2023-09-09  0:39                     ` Richard Stallman
2023-09-09 10:32                       ` Ihor Radchenko
2023-09-10  0:22                         ` Richard Stallman
2023-09-10  8:36                           ` Ihor Radchenko
2023-09-13 23:53                             ` Richard Stallman
2023-09-20 12:59                               ` Ihor Radchenko
2023-09-05  0:30           ` Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged? Richard Stallman
2023-09-05  0:41             ` Emanuel Berg
2023-09-08 17:54               ` Emanuel Berg
2023-09-05  4:37             ` tomas
2023-09-05  5:53               ` Ihor Radchenko
2023-09-05  6:28                 ` tomas
2023-09-05 11:06             ` Adam Porter
2023-09-05 11:26             ` Lynn Winebarger
2023-09-05 14:11             ` Alan Mackenzie
2023-09-08  1:01               ` Richard Stallman
2023-09-08  2:45                 ` Po Lu
2023-09-10  0:24                   ` Richard Stallman
2023-09-05  8:14         ` Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp? Ulrich Mueller
2023-08-28 19:53 ` Emanuel Berg
2023-08-29  9:19   ` Alan Mackenzie
2023-08-29 10:36   ` João Távora
2023-08-29 11:09     ` Ihor Radchenko
2023-08-29 11:20       ` João Távora
2023-08-30 20:48         ` Sean Whitton
2023-08-30 20:59           ` João Távora
2023-09-02 23:12     ` Stefan Monnier via Emacs development discussions.
2023-09-03  0:18       ` Emanuel Berg
2023-09-03 12:27       ` João Távora
2023-08-29 12:54 ` Philip Kaludercic
2023-08-29 13:23   ` Alan Mackenzie
2023-09-02 23:09   ` Stefan Monnier via Emacs development discussions.
2023-08-29 16:28 ` LdBeth
2023-08-29 20:09 ` Stefan Kangas
2023-08-30 10:31   ` Alan Mackenzie
2023-08-30 17:36     ` Stefan Kangas
2023-08-30 18:03       ` Alan Mackenzie
2023-08-30 18:17         ` Stefan Kangas
2023-09-02 15:06           ` Alan Mackenzie [this message]
2023-09-02 15:17             ` Eli Zaretskii
2023-09-02 19:43               ` Alan Mackenzie
2023-09-03  4:42                 ` Eli Zaretskii
2023-09-03 10:48                   ` Alan Mackenzie
2023-09-03 11:02                     ` Eli Zaretskii
2023-09-03 13:24                       ` Alan Mackenzie
2023-09-02 19:20             ` Philip Kaludercic
2023-09-02 19:37               ` Stefan Kangas
2023-09-02 19:58               ` Alan Mackenzie
2023-09-04 11:12                 ` Lynn Winebarger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZPNPhh_My1P6k0vw@ACM \
    --to=acm@muc.de \
    --cc=emacs-devel@gnu.org \
    --cc=mattiase@acm.org \
    --cc=stefankangas@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.