šŸš€ go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: gmane.emacs.devel
35 messages
35 total messages Started by Alan Mackenzie Mon, 28 Aug 2023 19:37
Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307421
Author: Alan Mackenzie
Date: Mon, 28 Aug 2023 19:37
50 lines
1723 bytes
Hello, Emacs.

In C, we have the very useful conditional compilation directives
introduced by #if or #ifdef, etc., which end at #end.

In Emacs Lisp we have no such construct.  This is a Bad Thing.

More and more, especially recently, irritating warning messages are
occurring for, for example, obsolete variables and functions inside
conditionals which ensure they aren't used.  For example:

    (when (< emacs-major-version 24)
      (defadvice .....))

produces the warning about defadvice being obsolete.  (I haven't actually
tested this example).  What we really want here is for the defadvice only
to be _compiled_ when (< emacs-major-version 24), rather than compiled
unconditionally and not run.

I propose a new function, hash-if, which would do what we want.  The
above example could then be written something like:

    (hash-if (< emacs-major-version 24)
        (defadvice .....)
      (advice-add .....))

..  This is not actually all that difficult to write.  My first attempt
uses a compiler-macro, and looks like this:

    (defun hash-if (condition if-part &rest else-part)
      "A compiler macro analogous to C's #if.
    CONDITION is evaluated at compile time.  If it is non-nil,
    IF-PART gets compiled.  Otherwise ELSE-PART (enclosed in a
    `progn') gets compiled."
      (declare (indent 2))
      (error "hash-if has been called directly"))

    (put 'hash-if 'compiler-macro
         (lambda (form condition if-part &rest else-part)
           (if (eval condition lexical-binding)
               if-part
             (cons 'progn else-part))))

..  I propose adding it to subr.el, just before (defmacro when ....).

What do people think about this?

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307426
Author: Alan Mackenzie
Date: Mon, 28 Aug 2023 20:06
51 lines
1940 bytes
Hello, Ulrich.

On Mon, Aug 28, 2023 at 21:47:57 +0200, Ulrich Mueller wrote:
> >>>>> On Mon, 28 Aug 2023, Alan Mackenzie wrote:

> > In C, we have the very useful conditional compilation directives
> > introduced by #if or #ifdef, etc., which end at #end.

> > In Emacs Lisp we have no such construct.  This is a Bad Thing.

> > More and more, especially recently, irritating warning messages are
> > occurring for, for example, obsolete variables and functions inside
> > conditionals which ensure they aren't used.  For example:

> >     (when (< emacs-major-version 24)
> >       (defadvice .....))

> > produces the warning about defadvice being obsolete.  (I haven't actually
> > tested this example).  What we really want here is for the defadvice only
> > to be _compiled_ when (< emacs-major-version 24), rather than compiled
> > unconditionally and not run.

> I believe (eval-when-compile (< emacs-major-version 24)) would work?

I've twisted my head into knots in the past trying to work out how to
use eval-when/and-compile for this purpose.  The point is, I don't want
the defadvice to be evaluated at compile time; I just want it to be
compiled (or not).

> > I propose a new function, hash-if, which would do what we want.  The
> > above example could then be written something like:

> >     (hash-if (< emacs-major-version 24)
> >         (defadvice .....)
> >       (advice-add .....))

> But the old Emacs version wouldn't have the function, so it couldn't be
> used like this. What am I missing?

That's a very good point.  I would propose that we suggest to package
maintainers that they include the entire source of hash-if inside a
suitable conditional in their packages.  It's only 13 lines of code,
including a doc string.

It would appear that the compiler-macro mechanism existed at the latest
in Emacs 21.4.  I don't know how well it worked in these earlier
versions.

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307432
Author: Alan Mackenzie
Date: Mon, 28 Aug 2023 21:46
36 lines
1289 bytes
Hello, Ulrich.

On Mon, Aug 28, 2023 at 23:01:53 +0200, Ulrich Mueller wrote:
> >>>>> On Mon, 28 Aug 2023, Alan Mackenzie wrote:

> >> >     (when (< emacs-major-version 24)
> >> >       (defadvice .....))

> >> I believe (eval-when-compile (< emacs-major-version 24)) would work?

> > I've twisted my head into knots in the past trying to work out how to
> > use eval-when/and-compile for this purpose.  The point is, I don't want
> > the defadvice to be evaluated at compile time; I just want it to be
> > compiled (or not).

> Sorry, I should have been clearer. The full construct would look like
> this:

>     (when (eval-when-compile (< emacs-major-version 24))
>       (defadvice .....))

Ah!  So the eval-when-compile gets compiled to a constant nil or t, and
the byte compiler optimises the test of this out, either compiling or
not compiling the (defadvice .....).  Thanks!  I hadn't been aware of
that little detail.

> So only the test would be evaluated at compile time, the defadvice
> itself would be compiled normally (or not, if the test fails).

However, when evaluating the containing defun/defmacro rather than byte
compiling it, the irritating warning message will appear with the e-w-c
strategem, but not with hash-if.  ;-)

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307422
Author: Ulrich Mueller
Date: Mon, 28 Aug 2023 21:47
31 lines
1168 bytes
>>>>> On Mon, 28 Aug 2023, Alan Mackenzie wrote:

> In C, we have the very useful conditional compilation directives
> introduced by #if or #ifdef, etc., which end at #end.

> In Emacs Lisp we have no such construct.  This is a Bad Thing.

> More and more, especially recently, irritating warning messages are
> occurring for, for example, obsolete variables and functions inside
> conditionals which ensure they aren't used.  For example:

>     (when (< emacs-major-version 24)
>       (defadvice .....))

> produces the warning about defadvice being obsolete.  (I haven't actually
> tested this example).  What we really want here is for the defadvice only
> to be _compiled_ when (< emacs-major-version 24), rather than compiled
> unconditionally and not run.

I believe (eval-when-compile (< emacs-major-version 24)) would work?

> I propose a new function, hash-if, which would do what we want.  The
> above example could then be written something like:

>     (hash-if (< emacs-major-version 24)
>         (defadvice .....)
>       (advice-add .....))

But the old Emacs version wouldn't have the function, so it couldn't be
used like this. What am I missing?

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307424
Author: Emanuel Berg
Date: Mon, 28 Aug 2023 21:53
20 lines
482 bytes
Alan Mackenzie wrote:

> In C, we have the very useful conditional compilation
> directives introduced by #if or #ifdef, etc., which end at
> #end.

Those are directives to the C preprocessor and some people say
it is a sign of weakness such a thing is even necessary to
begin with.

Let's see if they are right!

What problem do you have? If we can solve it in Elisp, we
cannot say those people saying that are wrong.

--
underground experts united
https://dataswamp.org/~incal


Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307429
Author: Ulrich Mueller
Date: Mon, 28 Aug 2023 23:01
21 lines
725 bytes
>>>>> On Mon, 28 Aug 2023, Alan Mackenzie wrote:

>> >     (when (< emacs-major-version 24)
>> >       (defadvice .....))

>> I believe (eval-when-compile (< emacs-major-version 24)) would work?

> I've twisted my head into knots in the past trying to work out how to
> use eval-when/and-compile for this purpose.  The point is, I don't want
> the defadvice to be evaluated at compile time; I just want it to be
> compiled (or not).

Sorry, I should have been clearer. The full construct would look like
this:

    (when (eval-when-compile (< emacs-major-version 24))
      (defadvice .....))

So only the test would be evaluated at compile time, the defadvice
itself would be compiled normally (or not, if the test fails).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307458
Author: Alan Mackenzie
Date: Tue, 29 Aug 2023 09:19
40 lines
1126 bytes
Hello, Emanuel.

On Mon, Aug 28, 2023 at 21:53:04 +0200, Emanuel Berg wrote:
> Alan Mackenzie wrote:

> > In C, we have the very useful conditional compilation
> > directives introduced by #if or #ifdef, etc., which end at
> > #end.

> Those are directives to the C preprocessor and some people say
> it is a sign of weakness such a thing is even necessary to
> begin with.

I think these people tend to be those living in an ideal world rather
than the real world.

> Let's see if they are right!

> What problem do you have?

The one I outlined in my original post: the use of obsolete
functions/variables inside conditionals which ensure they only get
called/referenced in older versions of Emacs.  These obsolete
objects are getting needlessly compiled in the master branch, giving
rise to lots of irritating warning messages.

It's a problem which arises in packages rather than in the core.

> If we can solve it in Elisp, we cannot say those people saying that
> are wrong.

My proposed solution is in Elisp.

> --
> underground experts united
> https://dataswamp.org/~incal

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307461
Author: Ihor Radchenko
Date: Tue, 29 Aug 2023 11:09
15 lines
445 bytes
João TÔvora <joaotavora@gmail.com> writes:

> FWIW, Common Lisp has reader macros to solve the problem:
> http://clhs.lisp.se/Body/24_aba.htm

Elisp also has reader macros ;)
See lisp/emacs-lisp/backquote.el

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307482
Author: LdBeth
Date: Tue, 29 Aug 2023 11:28
38 lines
1226 bytes
>>>>> In <ZOz3lR_4Al88SEJ_@ACM>
>>>>>	Alan Mackenzie <acm@muc.de> wrote:
acm> Hello, Emacs.

acm> In Emacs Lisp we have no such construct.  This is a Bad Thing.

acm> More and more, especially recently, irritating warning messages are
acm> occurring for, for example, obsolete variables and functions inside
acm> conditionals which ensure they aren't used.  For example:

acm>     (when (< emacs-major-version 24)
acm>       (defadvice .....))

acm> produces the warning about defadvice being obsolete.  (I haven't actually
acm> tested this example).  What we really want here is for the defadvice only
acm> to be _compiled_ when (< emacs-major-version 24), rather than compiled
acm> unconditionally and not run.

acm> I propose a new function, hash-if, which would do what we want.  The
acm> above example could then be written something like:

acm>     (hash-if (< emacs-major-version 24)
acm>         (defadvice .....)
acm>       (advice-add .....))

Have a look at `static.el' from APEL

https://github.com/wanderlust/apel

It provides `static-if' and other useful macros.

(defmacro static-if (cond then &rest else)
  "Like `if', but evaluate COND at compile time."
  (if (eval cond)
      then
    `(progn ,@ else)))


Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307459
Author: =?UTF-8?B?Sm/Do2
Date: Tue, 29 Aug 2023 11:36
67 lines
2503 bytes
--00000000000071873606040d635c
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Tue, Aug 29, 2023, 03:21 Emanuel Berg <incal@dataswamp.org> wrote:

> Alan Mackenzie wrote:
>
> > In C, we have the very useful conditional compilation
> > directives introduced by #if or #ifdef, etc., which end at
> > #end.
>
> Those are directives to the C preprocessor and some people say
> it is a sign of weakness such a thing is even necessary to
> begin with.
>
> Let's see if they are right!
>
> What problem do you have? If we can solve it in Elisp, we
> cannot say those people saying that are wrong.
>

FWIW, Common Lisp has reader macros to solve the problem:
http://clhs.lisp.se/Body/24_aba.htm

If Elisp had a better, more programmable reader, this would be the way to
solve it IMO

João

>

--00000000000071873606040d635c
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Aug 29, 2023, 03:21 Emanuel Berg <<a href="mailto:incal@dataswamp.org" target="_blank" rel="noreferrer">incal@dataswamp.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Alan Mackenzie wrote:<br>
<br>
> In C, we have the very useful conditional compilation<br>
> directives introduced by #if or #ifdef, etc., which end at<br>
> #end.<br>
<br>
Those are directives to the C preprocessor and some people say<br>
it is a sign of weakness such a thing is even necessary to<br>
begin with.<br>
<br>
Let's see if they are right!<br>
<br>
What problem do you have? If we can solve it in Elisp, we<br>
cannot say those people saying that are wrong.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">FWIW, Common Lisp has reader macros to solve the problem: <a href="http://clhs.lisp.se/Body/24_aba.htm" target="_blank" rel="noreferrer">http://clhs.lisp.se/Body/24_aba.htm</a></div><div dir="auto"><br></div><div dir="auto">If Elisp had a better, more programmable reader, this would be the way to solve it IMO</div><div dir="auto"><br></div><div dir="auto">João</div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote></div></div></div>

--00000000000071873606040d635c--

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307462
Author: =?UTF-8?B?Sm/Do2
Date: Tue, 29 Aug 2023 12:20
19 lines
693 bytes
On Tue, Aug 29, 2023 at 12:09 PM Ihor Radchenko <yantar92@posteo.net> wrote:
>
> João TÔvora <joaotavora@gmail.com> writes:
>
> > FWIW, Common Lisp has reader macros to solve the problem:
> > http://clhs.lisp.se/Body/24_aba.htm
>
> Elisp also has reader macros ;)
> See lisp/emacs-lisp/backquote.el

Of course it has many more even, but the problem is that such things
are hardcoded in C even if part of the implementation then jumps to Lisp.
See lread.c around line 4318 for how backquote is  hardcoded.  In Common
Lisp there is a programmable mechanism for adding such macros entirely
within the language.  So don't be fooled, Elisp simply doesn't have that.

João

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307474
Author: Philip Kaluderci
Date: Tue, 29 Aug 2023 12:54
60 lines
2199 bytes
Alan Mackenzie <acm@muc.de> writes:

> Hello, Emacs.
>
> In C, we have the very useful conditional compilation directives
> introduced by #if or #ifdef, etc., which end at #end.
>
> In Emacs Lisp we have no such construct.  This is a Bad Thing.
>
> More and more, especially recently, irritating warning messages are
> occurring for, for example, obsolete variables and functions inside
> conditionals which ensure they aren't used.  For example:
>
>     (when (< emacs-major-version 24)
>       (defadvice .....))
>
> produces the warning about defadvice being obsolete.  (I haven't actually
> tested this example).  What we really want here is for the defadvice only
> to be _compiled_ when (< emacs-major-version 24), rather than compiled
> unconditionally and not run.

In this specific case, would it be possible to use the nadvice
compatibility package on GNU ELPA?

> I propose a new function, hash-if, which would do what we want.  The
> above example could then be written something like:
>
>     (hash-if (< emacs-major-version 24)
>         (defadvice .....)
>       (advice-add .....))
>
> ..  This is not actually all that difficult to write.  My first attempt
> uses a compiler-macro, and looks like this:
>
>     (defun hash-if (condition if-part &rest else-part)
>       "A compiler macro analogous to C's #if.
>     CONDITION is evaluated at compile time.  If it is non-nil,
>     IF-PART gets compiled.  Otherwise ELSE-PART (enclosed in a
>     `progn') gets compiled."
>       (declare (indent 2))
>       (error "hash-if has been called directly"))
>
>     (put 'hash-if 'compiler-macro
>          (lambda (form condition if-part &rest else-part)
>            (if (eval condition lexical-binding)
>                if-part
>              (cons 'progn else-part))))

Would something like work as well:

--8<---------------cut here---------------start------------->8---
(defmacro cif (test then &rest else)
  "Evaluate TEST during macro-expansion and return THEN or ELSE."
  (if (eval test t) then else))
--8<---------------cut here---------------end--------------->8---

> ..  I propose adding it to subr.el, just before (defmacro when ....).
>
> What do people think about this?

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307476
Author: Alan Mackenzie
Date: Tue, 29 Aug 2023 13:23
81 lines
2902 bytes
Hello, Philip.

On Tue, Aug 29, 2023 at 12:54:17 +0000, Philip Kaludercic wrote:
> Alan Mackenzie <acm@muc.de> writes:

> > Hello, Emacs.

> > In C, we have the very useful conditional compilation directives
> > introduced by #if or #ifdef, etc., which end at #end.

> > In Emacs Lisp we have no such construct.  This is a Bad Thing.

> > More and more, especially recently, irritating warning messages are
> > occurring for, for example, obsolete variables and functions inside
> > conditionals which ensure they aren't used.  For example:

> >     (when (< emacs-major-version 24)
> >       (defadvice .....))

> > produces the warning about defadvice being obsolete.  (I haven't actually
> > tested this example).  What we really want here is for the defadvice only
> > to be _compiled_ when (< emacs-major-version 24), rather than compiled
> > unconditionally and not run.

> In this specific case, would it be possible to use the nadvice
> compatibility package on GNU ELPA?

I suspect it would be, yes.

> > I propose a new function, hash-if, which would do what we want.  The
> > above example could then be written something like:

> >     (hash-if (< emacs-major-version 24)
> >         (defadvice .....)
> >       (advice-add .....))

> > ..  This is not actually all that difficult to write.  My first attempt
> > uses a compiler-macro, and looks like this:

> >     (defun hash-if (condition if-part &rest else-part)
> >       "A compiler macro analogous to C's #if.
> >     CONDITION is evaluated at compile time.  If it is non-nil,
> >     IF-PART gets compiled.  Otherwise ELSE-PART (enclosed in a
> >     `progn') gets compiled."
> >       (declare (indent 2))
> >       (error "hash-if has been called directly"))

> >     (put 'hash-if 'compiler-macro
> >          (lambda (form condition if-part &rest else-part)
> >            (if (eval condition lexical-binding)
> >                if-part
> >              (cons 'progn else-part))))

> Would something like work as well:

> --8<---------------cut here---------------start------------->8---
> (defmacro cif (test then &rest else)
>   "Evaluate TEST during macro-expansion and return THEN or ELSE."
>   (if (eval test t) then else))
> --8<---------------cut here---------------end--------------->8---

Hah!  Trust me to build something twisted and complicated when there's a
simple solution which will do just as well!

I think the `else' needs a 'progn, though, like this:

    (if (eval test t) then (cons 'progn else))

, and the eval form probably wants to go into a condition-case for
Emacsen lacking the second parameter.  But I appreciate you put the code
together quickly, rather than working out every last detail.  Thanks!

> > ..  I propose adding it to subr.el, just before (defmacro when ....).

> > What do people think about this?

Yes, what do people think about the idea?

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307484
Author: Stefan Kangas
Date: Tue, 29 Aug 2023 22:09
17 lines
396 bytes
Alan Mackenzie <acm@muc.de> writes:

> What do people think about this?

I have two questions:

1. Would it be hard to make the byte-compiler not warn in the
situation you describe?

2. Isn't something like this enough to silence the byte-compiler?

    (defalias 'foo-defadvice
      (if (< emacs-major-version 24)
          'defadvice
        (lambda () (message "foo"))))
    (foo-defadvice)

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307510
Author: Alan Mackenzie
Date: Wed, 30 Aug 2023 10:31
35 lines
1049 bytes
Hello, Stefan.

On Tue, Aug 29, 2023 at 22:09:25 +0200, Stefan Kangas wrote:
> Alan Mackenzie <acm@muc.de> writes:

> > What do people think about this?

> I have two questions:

> 1. Would it be hard to make the byte-compiler not warn in the
> situation you describe?

(That situation being where an obsolete function/variable is tested for,
and is used or not used according to the result of the test.)  It would
not be too hard, and the scheme I'm proposing (with help from Philip K.)
is one way of doing this.

I'm sure there are other possible ways, too.

> 2. Isn't something like this enough to silence the byte-compiler?

>     (defalias 'foo-defadvice
>       (if (< emacs-major-version 24)
>           'defadvice
>         (lambda () (message "foo"))))
>     (foo-defadvice)

It may be, but it's clumsy.  We would need such an alias for _each_
function/variable which has been declared obsolete.  In my proposed
mechanism, by contrast, one would just need to replace an `if' form by a
`hash-if'.

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307520
Author: Alan Mackenzie
Date: Wed, 30 Aug 2023 18:03
63 lines
2667 bytes
Hello, Stefan.

On Wed, Aug 30, 2023 at 19:36:20 +0200, Stefan Kangas wrote:
> Alan Mackenzie <acm@muc.de> writes:

> > > 1. Would it be hard to make the byte-compiler not warn in the
> > > situation you describe?
> >
> > (That situation being where an obsolete function/variable is tested for,
> > and is used or not used according to the result of the test.)  It would
> > not be too hard, and the scheme I'm proposing (with help from Philip K.)
> > is one way of doing this.

> I'm asking because we already have special casing in place for
> (featurep 'xemacs) -- we just constant fold it -- so I'm wondering if
> it would make sense to do the same here.  See bytecomp.el:5671.

I looked at that, and came to the conclusion it doesn't make sense.  The
mechanics there would be to evaluate (if some-condition FOO BAR) at
compilation time and replace it with either FOO or BAR.  The problem is
some-condition can vary at run time, for example by setting an option,
so it would be more trouble than it's worth.

> It's not the same situation exactly though, as we will often be able
> to run bytecode from Emacs N+1 on Emacs N, whereas XEmacs/Emacs
> byte-code compatibility is both long gone and in all likelihood not
> coming back.

Indeed, not.

> > It may be, but it's clumsy.  We would need such an alias for _each_
> > function/variable which has been declared obsolete.  In my proposed
> > mechanism, by contrast, one would just need to replace an `if' form by a
> > `hash-if'.

> Right.  I guess this has been the state of the art in Emacs Lisp so
> far, though.  And then `hash-if' itself won't exist in Emacs 24
> either, of course, so depending on how ambitious people are with
> backwards-compatibility they'll have to lug around compatibility
> boiler-plate for that too.

The current size of hash-if, including doc-string, is 10 lines.  Add in
an extra line for (if (not fboundp 'hash-if) ....), and we come to 11
lines.  I think, given the heartaches and headaches suffered by package
maintainers when variables/functions become obsolete or vanish, this
would not be much of a hardship.

> If we do go with a new macro, I'd propose naming it `static-if' (as in
> APEL) instead of `hash-if', because the latter name seems to wrongly
> suggest that it has to do with hashing.

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.

> Our legacy is also older than even the C preprocessor.

:-)

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307519
Author: Stefan Kangas
Date: Wed, 30 Aug 2023 19:36
33 lines
1555 bytes
Alan Mackenzie <acm@muc.de> writes:

> > 1. Would it be hard to make the byte-compiler not warn in the
> > situation you describe?
>
> (That situation being where an obsolete function/variable is tested for,
> and is used or not used according to the result of the test.)  It would
> not be too hard, and the scheme I'm proposing (with help from Philip K.)
> is one way of doing this.

I'm asking because we already have special casing in place for
(featurep 'xemacs) -- we just constant fold it -- so I'm wondering if
it would make sense to do the same here.  See bytecomp.el:5671.  It's
not the same situation exactly though, as we will often be able to run
bytecode from Emacs N+1 on Emacs N, whereas XEmacs/Emacs byte-code
compatibility is both long gone and in all likelihood not coming back.

> It may be, but it's clumsy.  We would need such an alias for _each_
> function/variable which has been declared obsolete.  In my proposed
> mechanism, by contrast, one would just need to replace an `if' form by a
> `hash-if'.

Right.  I guess this has been the state of the art in Emacs Lisp so
far, though.  And then `hash-if' itself won't exist in Emacs 24
either, of course, so depending on how ambitious people are with
backwards-compatibility they'll have to lug around compatibility
boiler-plate for that too.

If we do go with a new macro, I'd propose naming it `static-if' (as in
APEL) instead of `hash-if', because the latter name seems to wrongly
suggest that it has to do with hashing.  Our legacy is also older than
even the C preprocessor.

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307522
Author: Stefan Kangas
Date: Wed, 30 Aug 2023 20:17
12 lines
582 bytes
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.

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307529
Author: Sean Whitton
Date: Wed, 30 Aug 2023 21:48
16 lines
569 bytes
Hello,

On Tue 29 Aug 2023 at 12:20pm +01, João TÔvora wrote:

> Of course it has many more even, but the problem is that such things
> are hardcoded in C even if part of the implementation then jumps to Lisp.
> See lread.c around line 4318 for how backquote is  hardcoded.  In Common
> Lisp there is a programmable mechanism for adding such macros entirely
> within the language.  So don't be fooled, Elisp simply doesn't have that.

It's a deliberate choice, right?  As part of ideas about keeping elisp
simpler than something like CL.

-- 
Sean Whitton

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307530
Author: =?UTF-8?B?Sm/Do2
Date: Wed, 30 Aug 2023 21:59
23 lines
746 bytes
On Wed, Aug 30, 2023 at 9:48 PM Sean Whitton <spwhitton@spwhitton.name> wrote:
>
> Hello,
>
> On Tue 29 Aug 2023 at 12:20pm +01, João TÔvora wrote:
>
> > Of course it has many more even, but the problem is that such things
> > are hardcoded in C even if part of the implementation then jumps to Lisp.
> > See lread.c around line 4318 for how backquote is  hardcoded.  In Common
> > Lisp there is a programmable mechanism for adding such macros entirely
> > within the language.  So don't be fooled, Elisp simply doesn't have that.
>
> It's a deliberate choice, right?  As part of ideas about keeping elisp
> simpler than something like CL.

Yeah, you "keep something simple" then Greenspuns's 10th kicks in.

João

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307545
Author: Richard Stallman
Date: Wed, 30 Aug 2023 22:07
35 lines
1273 bytes
[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > >     (when (eval-when-compile (< emacs-major-version 24))
  > >       (defadvice .....))

  > However, when evaluating the containing defun/defmacro rather than byte
  > compiling it, the irritating warning message will appear with the e-w-c
  > strategem, but not with hash-if.  ;-)

How about making the byte compiler recognize the construct

 (if (< emacs-major-version NUMBER) ...)

and do this optimization on it?

I think that will DTRT when compiled and when interpreted,
and it won't require changes in the code of the programs that use it.

That will handle `when' and `unless', since they expand into `if'.

It may be necessary to implement this in two places, one for inside of
function bodies and one for top level (outside of function
definitions).  But the code for this should be so short that having
two is hardly much loss.

--
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)



Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307575
Author: Alan Mackenzie
Date: Thu, 31 Aug 2023 07:50
60 lines
2520 bytes
Hello, Richard.

On Wed, Aug 30, 2023 at 22:07:04 -0400, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]

>   > >     (when (eval-when-compile (< emacs-major-version 24))
>   > >       (defadvice .....))

>   > However, when evaluating the containing defun/defmacro rather than byte
>   > compiling it, the irritating warning message will appear with the e-w-c
>   > strategem, but not with hash-if.  ;-)

> How about making the byte compiler recognize the construct

>  (if (< emacs-major-version NUMBER) ...)

> and do this optimization on it?

> I think that will DTRT when compiled and when interpreted,
> and it won't require changes in the code of the programs that use it.

The conditions we want to test are sometimes/frequently expressed in
terms of the (non-)existence of variables, etc.  It would be
inconvenient for package maintainers to have to determine "critical"
Emacs version numbers to use.  Also, it is possible for the condition to
be dependent upon a minor version number, maybe.

Why do you think a more restricted test of the version number would be
better than a more general test?

The changes to the code to convert from `if' to `hash-if' (or
`static-if' as has been proposed) are minor - they just need amending
the if/when/unless forms to hash-if.  Also, there will not be all that
many of them.  That way, we have more flexibility than testing just the
major version number.

> That will handle `when' and `unless', since they expand into `if'.

> It may be necessary to implement this in two places, one for inside of
> function bodies and one for top level (outside of function
> definitions).  But the code for this should be so short that having
> two is hardly much loss.

The macro hash-if itself is very short, the current version taking 13
lines (including doc string), including a condition-case checking for
`eval' having only one parameter.  The idea is that a package maintainer
can copy this directly into her source code (inside an (if (not (fboundp
'hash-if)) ....)) so the mechanism will work also in older Emacsen.

> --
> Dr Richard Stallman (https://stallman.org)
> Chief GNUisance of the GNU Project (https://gnu.org)
> Founder, Free Software Foundation (https://fsf.org)
> Internet Hall-of-Famer (https://internethalloffame.org)

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307876
Author: Stefan Kangas
Date: Sat, 02 Sep 2023 12:37
19 lines
716 bytes
Philip Kaludercic <philipk@posteo.net> writes:

> Alan Mackenzie <acm@muc.de> writes:
>
>> +;; 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.
>
> Is this really a concern for the version that would be added to Emacs itself?

I think we can have our cake and eat it by adding the non-nil LEXICAL
parameter and changing the comment to:

    ;; Remove the &optional parameter LEXICAL for `eval' if this needs
    ;; to work in Emacs version 24.3 or older.

That way, there can be no absolutely confusion about when it would need
to be removed, and packages that don't need to will use lexical-binding.

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307864
Author: Alan Mackenzie
Date: Sat, 02 Sep 2023 15:06
144 lines
6002 bytes
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).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307865
Author: Eli Zaretskii
Date: Sat, 02 Sep 2023 18:17
56 lines
2500 bytes
> Date: Sat, 2 Sep 2023 15:06:46 +0000
> Cc: emacs-devel@gnu.org,
>  Mattias EngdegƄrd <mattiase@acm.org>
> From: Alan Mackenzie <acm@muc.de>
>
> +@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.

Thanks, but I think the references to #if make the documentation less
helpful than it could be.  This manual is for Lisp programmers, and
those are not necessarily familiar with C and its preprocessor
directives.  So I think it would be better if you removed the
references to cpp.  If you think removing that would make the
documentation less self-explanatory, I suggest to add explanations
that are based on Lisp and on typical situations while writing Lisp
programs, not on cpp.

> --- 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'.

Same here.  Here, it is actually worse: "based on C language's #if"
could be misinterpreted as meaning the implementation is based on #if
in some way.  I would suggest the following text in NEWS:

 ** New macro 'static-if' for conditional byte-compilation of code.
 This macro hides a form from the byte-compiler based on a
 compile-time condition.  This is handy for avoiding byte-compilation
 warnings about code that will never actually run under some
 conditions.

Thanks.

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307891
Author: Stefan Monnier v
Date: Sat, 02 Sep 2023 19:09
25 lines
892 bytes
> --8<---------------cut here---------------start------------->8---
> (defmacro cif (test then &rest else)
>   "Evaluate TEST during macro-expansion and return THEN or ELSE."
>   (if (eval test t) then else))
> --8<---------------cut here---------------end--------------->8---

FWIW I've used such macros in packages under the name
`<PKG>--if-when-compile`.

Also, FWIW, I've used the following variant to let the
compile-time check be reconsidered at runtime:

    (defmacro TeX--if-macro-fboundp (name then &rest else)
      "..."
      (declare (indent 2) (debug (symbolp form &rest form)))
      (if (fboundp name)             ;If macro exists at compile-time, just use it.
          then
        `(if (fboundp ',name)               ;Else, check if it exists at run-time.
             (eval ',then)                  ;If it does, then run the then code.
           ,@else)))


-- Stefan


Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307892
Author: Stefan Monnier v
Date: Sat, 02 Sep 2023 19:12
27 lines
897 bytes
>> > In C, we have the very useful conditional compilation
>> > directives introduced by #if or #ifdef, etc., which end at
>> > #end.
>>
>> Those are directives to the C preprocessor and some people say
>> it is a sign of weakness such a thing is even necessary to
>> begin with.
>>
>> Let's see if they are right!
>>
>> What problem do you have? If we can solve it in Elisp, we
>> cannot say those people saying that are wrong.
>>
>
> FWIW, Common Lisp has reader macros to solve the problem:
> http://clhs.lisp.se/Body/24_aba.htm

I don't see why reader macros would be needed here.  Reader macros are
useful to introduce funny new shorthands or to avoid *reading* a chunk
of code (e.g. because it uses some unsupported funny syntax) but in the
present case we can read both branches of the `if` just fine, we just
want to throw away one of the two before we macro-expand it.


        Stefan


Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307875
Author: Philip Kaluderci
Date: Sat, 02 Sep 2023 19:20
23 lines
929 bytes
Alan Mackenzie <acm@muc.de> writes:

> +;; 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.

Is this really a concern for the version that would be added to Emacs itself?

> +(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)))


Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307877
Author: Alan Mackenzie
Date: Sat, 02 Sep 2023 19:43
91 lines
3856 bytes
Hello, Eli.

Thanks for the feedback.

On Sat, Sep 02, 2023 at 18:17:51 +0300, Eli Zaretskii wrote:
> > Date: Sat, 2 Sep 2023 15:06:46 +0000
> > Cc: emacs-devel@gnu.org,
> >  Mattias EngdegƄrd <mattiase@acm.org>
> > From: Alan Mackenzie <acm@muc.de>

> > +@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.

> Thanks, but I think the references to #if make the documentation less
> helpful than it could be.  This manual is for Lisp programmers, and
> those are not necessarily familiar with C and its preprocessor
> directives.  So I think it would be better if you removed the
> references to cpp.  If you think removing that would make the
> documentation less self-explanatory, I suggest to add explanations
> that are based on Lisp and on typical situations while writing Lisp
> programs, not on cpp.

OK, I've removed the bit "It is inspired by .... C like languages"
leaving just "It is patterned after the special form @code{if} ..." of
the sentence.

I thought the comparison with C might be helpful for a lot of users, but
I can see how it might be confusing instead.

> > --- 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'.

> Same here.  Here, it is actually worse: "based on C language's #if"
> could be misinterpreted as meaning the implementation is based on #if
> in some way.  I would suggest the following text in NEWS:

>  ** New macro 'static-if' for conditional byte-compilation of code.
>  This macro hides a form from the byte-compiler based on a
>  compile-time condition.  This is handy for avoiding byte-compilation
>  warnings about code that will never actually run under some
>  conditions.

static-if actually works for interpreted compilation as well as byte
compilation, so I've removed two "byte-"s from your text, leaving:

+++
** New macro 'static-if' for conditional compilation of code.
This macro hides a form from the compiler based on a compile-time
condition.  This is handy for avoiding byte-compilation warnings about
code that will never actually run under some conditions.

I think it's now ready to commit, except ....

I've had some private email which suggested that perhaps static-if
should not include the condition-case which copes with an ancient eval
from before lexical binding.  I can see some merit in the argument
(lexical binding happened in 24.1, I think), but on the other hand, that
extreme backwards compatibility doesn't really cost us anything
(static-if is just 13 lines of code).

What do you think?

> Thanks.

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307879
Author: Alan Mackenzie
Date: Sat, 02 Sep 2023 19:58
34 lines
1309 bytes
Hello, Philip.

On Sat, Sep 02, 2023 at 19:20:29 +0000, Philip Kaludercic wrote:
> Alan Mackenzie <acm@muc.de> writes:

> > +;; 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.

> Is this really a concern for the version that would be added to Emacs
> itself?

The idea was that there would be just one version, and a package
maintainer could copy the 13 lines to the beginning of her package
inside something like (when (not (fboundp 'static-if)) ....), but
otherwise unchanged.

> > +(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)))

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307893
Author: Emanuel Berg
Date: Sun, 03 Sep 2023 02:18
42 lines
1406 bytes
Stefan Monnier via "Emacs development discussions." wrote:

>>>> In C, we have the very useful conditional compilation
>>>> directives introduced by #if or #ifdef, etc., which end
>>>> at #end.
>>>
>>> Those are directives to the C preprocessor and some people
>>> say it is a sign of weakness such a thing is even
>>> necessary to begin with.
>>>
>>> Let's see if they are right!
>>>
>>> What problem do you have? If we can solve it in Elisp, we
>>> cannot say those people saying that are wrong.
>>
>> FWIW, Common Lisp has reader macros to solve the problem:
>> http://clhs.lisp.se/Body/24_aba.htm
>
> I don't see why reader macros would be needed here.
> Reader macros are useful to introduce funny new shorthands
> or to avoid *reading* a chunk of code (e.g. because it uses
> some unsupported funny syntax) but in the present case we
> can read both branches of the `if` just fine, we just want
> to throw away one of the two before we macro-expand it.

In general, Lisp macros seem much more powerful and versatile
than the C preprocessor, and they are part of the language as
well.

But let's say preprocessor directives are part of the
C language as well then even tho it doesn't feel like
it, really.

The question is then, is there anything you can do with the
C preprocessor which you _cannot_ do in Lisp - with or
without macros?

--
underground experts united
https://dataswamp.org/~incal


Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307899
Author: Eli Zaretskii
Date: Sun, 03 Sep 2023 07:42
47 lines
2124 bytes
> Date: Sat, 2 Sep 2023 19:43:29 +0000
> Cc: stefankangas@gmail.com, emacs-devel@gnu.org, mattiase@acm.org
> From: Alan Mackenzie <acm@muc.de>
>
> > > ++++
> > > +** There is now conditional compilation, based on the C language's #if.
> > > +To use this, see the new macro 'static-if'.
>
> > Same here.  Here, it is actually worse: "based on C language's #if"
> > could be misinterpreted as meaning the implementation is based on #if
> > in some way.  I would suggest the following text in NEWS:
>
> >  ** New macro 'static-if' for conditional byte-compilation of code.
> >  This macro hides a form from the byte-compiler based on a
> >  compile-time condition.  This is handy for avoiding byte-compilation
> >  warnings about code that will never actually run under some
> >  conditions.
>
> static-if actually works for interpreted compilation as well as byte
> compilation, so I've removed two "byte-"s from your text, leaving:
>
> +++
> ** New macro 'static-if' for conditional compilation of code.
> This macro hides a form from the compiler based on a compile-time
> condition.  This is handy for avoiding byte-compilation warnings about
> code that will never actually run under some conditions.

What is "interpreted compilation" in Emacs?  I'm aware of only two
compilers in Emacs: the byte compiler and the native compiler.  So
when you talk about "the compiler" above, what does that allude to?

> I think it's now ready to commit, except ....
>
> I've had some private email which suggested that perhaps static-if
> should not include the condition-case which copes with an ancient eval
> from before lexical binding.  I can see some merit in the argument
> (lexical binding happened in 24.1, I think), but on the other hand, that
> extreme backwards compatibility doesn't really cost us anything
> (static-if is just 13 lines of code).
>
> What do you think?

I don't think I understand the issue: it was discussed in private
email , and you didn't tell enough for me to understand and form an
opinion.  What do you mean by "condition-case which copes with an
ancient eval from before lexical binding"?

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307935
Author: Alan Mackenzie
Date: Sun, 03 Sep 2023 10:48
77 lines
3356 bytes
Hello, Eli.

On Sun, Sep 03, 2023 at 07:42:13 +0300, Eli Zaretskii wrote:
> > Date: Sat, 2 Sep 2023 19:43:29 +0000
> > Cc: stefankangas@gmail.com, emacs-devel@gnu.org, mattiase@acm.org
> > From: Alan Mackenzie <acm@muc.de>

> > > > ++++
> > > > +** There is now conditional compilation, based on the C language's #if.
> > > > +To use this, see the new macro 'static-if'.

> > > Same here.  Here, it is actually worse: "based on C language's #if"
> > > could be misinterpreted as meaning the implementation is based on #if
> > > in some way.  I would suggest the following text in NEWS:

> > >  ** New macro 'static-if' for conditional byte-compilation of code.
> > >  This macro hides a form from the byte-compiler based on a
> > >  compile-time condition.  This is handy for avoiding byte-compilation
> > >  warnings about code that will never actually run under some
> > >  conditions.

> > static-if actually works for interpreted compilation as well as byte
> > compilation, so I've removed two "byte-"s from your text, leaving:

> > +++
> > ** New macro 'static-if' for conditional compilation of code.
> > This macro hides a form from the compiler based on a compile-time
> > condition.  This is handy for avoiding byte-compilation warnings about
> > code that will never actually run under some conditions.

> What is "interpreted compilation" in Emacs?  I'm aware of only two
> compilers in Emacs: the byte compiler and the native compiler.  So
> when you talk about "the compiler" above, what does that allude to?

I mean the defmacro and defun macros, particularly when invoked by C-M-x,
etc.  Do we have a generic term for these, regardless of whether they are
called interpretatively  or in the context of byte/native compilation?

> > I think it's now ready to commit, except ....

> > I've had some private email which suggested that perhaps static-if
> > should not include the condition-case which copes with an ancient eval
> > from before lexical binding.  I can see some merit in the argument
> > (lexical binding happened in 24.1, I think), but on the other hand, that
> > extreme backwards compatibility doesn't really cost us anything
> > (static-if is just 13 lines of code).

> > What do you think?

> I don't think I understand the issue: it was discussed in private
> email , and you didn't tell enough for me to understand and form an
> opinion.  What do you mean by "condition-case which copes with an
> ancient eval from before lexical binding"?

Sorry.  The idea is that package maintainers can copy the source of
static-if directly into their packages so as to be able to use it in
older Emacsen.

In the code for static-if, there's a call to eval with two
arguments, CONDITION and lexical-binding.  In (very) old versions of
Emacs, eval would only accept one argument, the form.  So in such an old
Emacs, static-if will throw a wrong-number-of-args (or void-variable)
error.

I have proposed catching this error with a condition-case and in the
handler, calling eval again with just one argument.

The other party in the email has opined that static-if should not contain
this condition-case mechanism, and anybody writing for such an old Emacs
should make their own adjustments.

Perhaps it's too small a point to be worth bothering about, but I thought
I'd ask your view anyway.

--
Alan Mackenzie (Nuremberg, Germany).

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307939
Author: =?UTF-8?B?Sm/Do2
Date: Sun, 03 Sep 2023 13:27
66 lines
3146 bytes
--0000000000004541320604738587
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Sun, Sep 3, 2023, 00:15 Stefan Monnier via Emacs development
discussions. <emacs-devel@gnu.org> wrote:

> >
> > FWIW, Common Lisp has reader macros to solve the problem:
> > http://clhs.lisp.se/Body/24_aba.htm
>
> I don't see why reader macros would be needed here.
>

I didn't say they are "needed" to solve it. I merely said they would. And
they do, quite effectively in Common Lisp, precisely for the C-like use
cases presented here as paradigmatic.

But as always there are multiple ways to skin a cat.

CL's is particularly good IMO, and much more versatile than what is being
proposed here. It skins this and more cats. For example it doesn't require
changing the indentation of the form being ifdef'ed out. And the property
of making some code invisible to the reader is great for adding/removing
arguments conditionally in calls based on read-time knowledge.

Anyway, I'm taking about a particular type of reader macro called "feature
expressions" and that's what I linked to.

João

--0000000000004541320604738587
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Sep 3, 2023, 00:15 Stefan Monnier via Emacs development discussions. <<a href="mailto:emacs-devel@gnu.org" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank">emacs-devel@gnu.org</a>> wrote:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
><br>
> FWIW, Common Lisp has reader macros to solve the problem:<br>
> <a href="http://clhs.lisp.se/Body/24_aba.htm" rel="noreferrer noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank">http://clhs.lisp.se/Body/24_aba.htm</a><br>
<br>
I don't see why reader macros would be needed here.  <br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">I didn't say they are "needed" to solve it. I merely said they would. And they do, quite effectively in Common Lisp, precisely for the C-like use cases presented here as paradigmatic.</div><div dir="auto"><br></div><div dir="auto">But as always there are multiple ways to skin a cat. </div><div dir="auto"><br></div><div dir="auto">CL's is particularly good IMO, and much more versatile than what is being proposed here. It skins this and more cats. For example it doesn't require changing the indentation of the form being ifdef'ed out. And the property of making some code invisible to the reader is great for adding/removing arguments conditionally in calls based on read-time knowledge. </div><div dir="auto"><br></div><div dir="auto">Anyway, I'm taking about a particular type of reader macro called "feature expressions" and that's what I linked to.</div><div dir="auto"><br></div><div dir="auto">João</div></div>

--0000000000004541320604738587--

Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
#307937
Author: Eli Zaretskii
Date: Sun, 03 Sep 2023 14:02
56 lines
2573 bytes
> Date: Sun, 3 Sep 2023 10:48:50 +0000
> Cc: stefankangas@gmail.com, emacs-devel@gnu.org, mattiase@acm.org
> From: Alan Mackenzie <acm@muc.de>
>
> > > static-if actually works for interpreted compilation as well as byte
> > > compilation, so I've removed two "byte-"s from your text, leaving:
>
> > > +++
> > > ** New macro 'static-if' for conditional compilation of code.
> > > This macro hides a form from the compiler based on a compile-time
> > > condition.  This is handy for avoiding byte-compilation warnings about
> > > code that will never actually run under some conditions.
>
> > What is "interpreted compilation" in Emacs?  I'm aware of only two
> > compilers in Emacs: the byte compiler and the native compiler.  So
> > when you talk about "the compiler" above, what does that allude to?
>
> I mean the defmacro and defun macros, particularly when invoked by C-M-x,
> etc.  Do we have a generic term for these, regardless of whether they are
> called interpretatively  or in the context of byte/native compilation?

"Evaluation"?

> > > I've had some private email which suggested that perhaps static-if
> > > should not include the condition-case which copes with an ancient eval
> > > from before lexical binding.  I can see some merit in the argument
> > > (lexical binding happened in 24.1, I think), but on the other hand, that
> > > extreme backwards compatibility doesn't really cost us anything
> > > (static-if is just 13 lines of code).
>
> > > What do you think?
>
> > I don't think I understand the issue: it was discussed in private
> > email , and you didn't tell enough for me to understand and form an
> > opinion.  What do you mean by "condition-case which copes with an
> > ancient eval from before lexical binding"?
>
> Sorry.  The idea is that package maintainers can copy the source of
> static-if directly into their packages so as to be able to use it in
> older Emacsen.
>
> In the code for static-if, there's a call to eval with two
> arguments, CONDITION and lexical-binding.  In (very) old versions of
> Emacs, eval would only accept one argument, the form.  So in such an old
> Emacs, static-if will throw a wrong-number-of-args (or void-variable)
> error.
>
> I have proposed catching this error with a condition-case and in the
> handler, calling eval again with just one argument.
>
> The other party in the email has opined that static-if should not contain
> this condition-case mechanism, and anybody writing for such an old Emacs
> should make their own adjustments.

I tend to agree with "the other party", FWIW.

Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads