unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
@ 2023-08-28 19:37 Alan Mackenzie
  2023-08-28 19:47 ` Ulrich Mueller
                   ` (4 more replies)
  0 siblings, 5 replies; 66+ messages in thread
From: Alan Mackenzie @ 2023-08-28 19:37 UTC (permalink / raw)
  To: emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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 19:53 ` Emanuel Berg
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 66+ messages in thread
From: Ulrich Mueller @ 2023-08-28 19:47 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

>>>>> 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?



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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 19:53 ` Emanuel Berg
  2023-08-29  9:19   ` Alan Mackenzie
  2023-08-29 10:36   ` João Távora
  2023-08-29 12:54 ` Philip Kaludercic
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 66+ messages in thread
From: Emanuel Berg @ 2023-08-28 19:53 UTC (permalink / raw)
  To: emacs-devel

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




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-28 19:47 ` Ulrich Mueller
@ 2023-08-28 20:06   ` Alan Mackenzie
  2023-08-28 21:01     ` Ulrich Mueller
  0 siblings, 1 reply; 66+ messages in thread
From: Alan Mackenzie @ 2023-08-28 20:06 UTC (permalink / raw)
  To: Ulrich Mueller; +Cc: emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-28 20:06   ` Alan Mackenzie
@ 2023-08-28 21:01     ` Ulrich Mueller
  2023-08-28 21:46       ` Alan Mackenzie
  0 siblings, 1 reply; 66+ messages in thread
From: Ulrich Mueller @ 2023-08-28 21:01 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Ulrich Mueller, emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-28 21:01     ` Ulrich Mueller
@ 2023-08-28 21:46       ` Alan Mackenzie
  2023-08-31  2:07         ` Richard Stallman
  2023-09-05  8:14         ` Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp? Ulrich Mueller
  0 siblings, 2 replies; 66+ messages in thread
From: Alan Mackenzie @ 2023-08-28 21:46 UTC (permalink / raw)
  To: Ulrich Mueller; +Cc: emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-28 19:53 ` Emanuel Berg
@ 2023-08-29  9:19   ` Alan Mackenzie
  2023-08-29 10:36   ` João Távora
  1 sibling, 0 replies; 66+ messages in thread
From: Alan Mackenzie @ 2023-08-29  9:19 UTC (permalink / raw)
  To: emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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-09-02 23:12     ` Stefan Monnier via Emacs development discussions.
  1 sibling, 2 replies; 66+ messages in thread
From: João Távora @ 2023-08-29 10:36 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 736 bytes --]

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

>

[-- Attachment #2: Type: text/html, Size: 1456 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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-09-02 23:12     ` Stefan Monnier via Emacs development discussions.
  1 sibling, 1 reply; 66+ messages in thread
From: Ihor Radchenko @ 2023-08-29 11:09 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

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>



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-29 11:09     ` Ihor Radchenko
@ 2023-08-29 11:20       ` João Távora
  2023-08-30 20:48         ` Sean Whitton
  0 siblings, 1 reply; 66+ messages in thread
From: João Távora @ 2023-08-29 11:20 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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 19:53 ` Emanuel Berg
@ 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
  4 siblings, 2 replies; 66+ messages in thread
From: Philip Kaludercic @ 2023-08-29 12:54 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

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?



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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.
  1 sibling, 0 replies; 66+ messages in thread
From: Alan Mackenzie @ 2023-08-29 13:23 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-28 19:37 Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp? Alan Mackenzie
                   ` (2 preceding siblings ...)
  2023-08-29 12:54 ` Philip Kaludercic
@ 2023-08-29 16:28 ` LdBeth
  2023-08-29 20:09 ` Stefan Kangas
  4 siblings, 0 replies; 66+ messages in thread
From: LdBeth @ 2023-08-29 16:28 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

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




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-28 19:37 Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp? Alan Mackenzie
                   ` (3 preceding siblings ...)
  2023-08-29 16:28 ` LdBeth
@ 2023-08-29 20:09 ` Stefan Kangas
  2023-08-30 10:31   ` Alan Mackenzie
  4 siblings, 1 reply; 66+ messages in thread
From: Stefan Kangas @ 2023-08-29 20:09 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

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)



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-29 20:09 ` Stefan Kangas
@ 2023-08-30 10:31   ` Alan Mackenzie
  2023-08-30 17:36     ` Stefan Kangas
  0 siblings, 1 reply; 66+ messages in thread
From: Alan Mackenzie @ 2023-08-30 10:31 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-30 10:31   ` Alan Mackenzie
@ 2023-08-30 17:36     ` Stefan Kangas
  2023-08-30 18:03       ` Alan Mackenzie
  0 siblings, 1 reply; 66+ messages in thread
From: Stefan Kangas @ 2023-08-30 17:36 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel, Mattias Engdegård

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.



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-30 17:36     ` Stefan Kangas
@ 2023-08-30 18:03       ` Alan Mackenzie
  2023-08-30 18:17         ` Stefan Kangas
  0 siblings, 1 reply; 66+ messages in thread
From: Alan Mackenzie @ 2023-08-30 18:03 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: emacs-devel, Mattias Engdegård

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-30 18:03       ` Alan Mackenzie
@ 2023-08-30 18:17         ` Stefan Kangas
  2023-09-02 15:06           ` Alan Mackenzie
  0 siblings, 1 reply; 66+ messages in thread
From: Stefan Kangas @ 2023-08-30 18:17 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel, Mattias Engdegård

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.



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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
  0 siblings, 1 reply; 66+ messages in thread
From: Sean Whitton @ 2023-08-30 20:48 UTC (permalink / raw)
  To: João Távora; +Cc: Ihor Radchenko, emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-30 20:48         ` Sean Whitton
@ 2023-08-30 20:59           ` João Távora
  0 siblings, 0 replies; 66+ messages in thread
From: João Távora @ 2023-08-30 20:59 UTC (permalink / raw)
  To: Sean Whitton; +Cc: Ihor Radchenko, emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-28 21:46       ` Alan Mackenzie
@ 2023-08-31  2:07         ` Richard Stallman
  2023-08-31  7:50           ` Alan Mackenzie
  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  8:14         ` Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp? Ulrich Mueller
  1 sibling, 2 replies; 66+ messages in thread
From: Richard Stallman @ 2023-08-31  2:07 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ulm, emacs-devel

[[[ 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)





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-31  2:07         ` Richard Stallman
@ 2023-08-31  7:50           ` Alan Mackenzie
  2023-09-04  1:34             ` Richard Stallman
  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
  1 sibling, 1 reply; 66+ messages in thread
From: Alan Mackenzie @ 2023-08-31  7:50 UTC (permalink / raw)
  To: Richard Stallman; +Cc: ulm, emacs-devel

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-30 18:17         ` Stefan Kangas
@ 2023-09-02 15:06           ` Alan Mackenzie
  2023-09-02 15:17             ` Eli Zaretskii
  2023-09-02 19:20             ` Philip Kaludercic
  0 siblings, 2 replies; 66+ messages in thread
From: Alan Mackenzie @ 2023-09-02 15:06 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: emacs-devel, Mattias Engdegård

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



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-02 15:06           ` Alan Mackenzie
@ 2023-09-02 15:17             ` Eli Zaretskii
  2023-09-02 19:43               ` Alan Mackenzie
  2023-09-02 19:20             ` Philip Kaludercic
  1 sibling, 1 reply; 66+ messages in thread
From: Eli Zaretskii @ 2023-09-02 15:17 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: stefankangas, emacs-devel, mattiase

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-02 15:06           ` Alan Mackenzie
  2023-09-02 15:17             ` Eli Zaretskii
@ 2023-09-02 19:20             ` Philip Kaludercic
  2023-09-02 19:37               ` Stefan Kangas
  2023-09-02 19:58               ` Alan Mackenzie
  1 sibling, 2 replies; 66+ messages in thread
From: Philip Kaludercic @ 2023-09-02 19:20 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Stefan Kangas, emacs-devel, Mattias Engdegård

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




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-02 19:20             ` Philip Kaludercic
@ 2023-09-02 19:37               ` Stefan Kangas
  2023-09-02 19:58               ` Alan Mackenzie
  1 sibling, 0 replies; 66+ messages in thread
From: Stefan Kangas @ 2023-09-02 19:37 UTC (permalink / raw)
  To: Philip Kaludercic, Alan Mackenzie, Stefan Monnier
  Cc: emacs-devel, Mattias Engdegård

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.



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-02 15:17             ` Eli Zaretskii
@ 2023-09-02 19:43               ` Alan Mackenzie
  2023-09-03  4:42                 ` Eli Zaretskii
  0 siblings, 1 reply; 66+ messages in thread
From: Alan Mackenzie @ 2023-09-02 19:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: stefankangas, emacs-devel, mattiase

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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
  1 sibling, 1 reply; 66+ messages in thread
From: Alan Mackenzie @ 2023-09-02 19:58 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: Stefan Kangas, emacs-devel, Mattias Engdegård

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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.
  1 sibling, 0 replies; 66+ messages in thread
From: Stefan Monnier via Emacs development discussions. @ 2023-09-02 23:09 UTC (permalink / raw)
  To: emacs-devel

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




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-29 10:36   ` João Távora
  2023-08-29 11:09     ` Ihor Radchenko
@ 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
  1 sibling, 2 replies; 66+ messages in thread
From: Stefan Monnier via Emacs development discussions. @ 2023-09-02 23:12 UTC (permalink / raw)
  To: emacs-devel

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




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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
  1 sibling, 0 replies; 66+ messages in thread
From: Emanuel Berg @ 2023-09-03  0:18 UTC (permalink / raw)
  To: emacs-devel

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




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-02 19:43               ` Alan Mackenzie
@ 2023-09-03  4:42                 ` Eli Zaretskii
  2023-09-03 10:48                   ` Alan Mackenzie
  0 siblings, 1 reply; 66+ messages in thread
From: Eli Zaretskii @ 2023-09-03  4:42 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: stefankangas, emacs-devel, mattiase

> 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"?



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-03  4:42                 ` Eli Zaretskii
@ 2023-09-03 10:48                   ` Alan Mackenzie
  2023-09-03 11:02                     ` Eli Zaretskii
  0 siblings, 1 reply; 66+ messages in thread
From: Alan Mackenzie @ 2023-09-03 10:48 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: stefankangas, emacs-devel, mattiase

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-03 10:48                   ` Alan Mackenzie
@ 2023-09-03 11:02                     ` Eli Zaretskii
  2023-09-03 13:24                       ` Alan Mackenzie
  0 siblings, 1 reply; 66+ messages in thread
From: Eli Zaretskii @ 2023-09-03 11:02 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: stefankangas, emacs-devel, mattiase

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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
  1 sibling, 0 replies; 66+ messages in thread
From: João Távora @ 2023-09-03 12:27 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1021 bytes --]

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

[-- Attachment #2: Type: text/html, Size: 1774 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-03 11:02                     ` Eli Zaretskii
@ 2023-09-03 13:24                       ` Alan Mackenzie
  0 siblings, 0 replies; 66+ messages in thread
From: Alan Mackenzie @ 2023-09-03 13:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: stefankangas, emacs-devel, mattiase

Hello, Eli.

On Sun, Sep 03, 2023 at 14:02:50 +0300, Eli Zaretskii wrote:
> > 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>

[ .... ]

> > > 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"?

That's not quite there, I don't think.  We really want a word which
denotes the setting of a symbol's function cell starting off with a
"source" form.

I'm afraid I forgot to amend the NEWS entry I've just committed.  I'll
think about that a little more.

[ .... ]

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

It's worth a lot.  I've taken the condition-case mechanism out.

I would also be closing the bug, were this a thread on the bug list.  ;-)

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-31  7:50           ` Alan Mackenzie
@ 2023-09-04  1:34             ` Richard Stallman
  2023-09-04 10:50               ` Alan Mackenzie
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Stallman @ 2023-09-04  1:34 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ulm, emacs-devel

[[[ 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. ]]]

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

People peopose to handle conditions about Emacs version numbers in
a more optimized way.  I propsed a simple syntax for that.
Isn't it better>

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

I don't dollow you, Haveb't we been talking about conditions on Emacs
versions all along in this discussion?  I did not propose that as a
change, I carried it along.

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

If people would like other tests too, I have nothing against them.
The issue is how to implement whatever tests we support.  If they can
be done at compiler time, isn't this the better implementation?

I guess I don't follow.  Why do you prefer `hash-if' rather
than this simple compile-time syntax?  Why change the syntax rather
than using the syntax we use now?


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





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-04  1:34             ` Richard Stallman
@ 2023-09-04 10:50               ` Alan Mackenzie
  2023-09-04 11:02                 ` tomas
  2023-09-06  0:58                 ` Richard Stallman
  0 siblings, 2 replies; 66+ messages in thread
From: Alan Mackenzie @ 2023-09-04 10:50 UTC (permalink / raw)
  To: Richard Stallman; +Cc: ulm, emacs-devel

Hello, Richard.

On Sun, Sep 03, 2023 at 21:34:08 -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. ]]]

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

> People propose to handle conditions about Emacs version numbers in
> a more optimized way.  I proposed a simple syntax for that.
> Isn't it better?

I don't think it is.

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

> I don't follow you, Haven't we been talking about conditions on Emacs
> versions all along in this discussion?  I did not propose that as a
> change, I carried it along.

For example, in CC Mode there is a chunk of code looking like ....

  (when (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
    (electric-indent-local-mode (if c-electric-flag 1 0)))

, and there are quite a few instances like it.  Here, there is a comment
about which versions are relevant, but that is somewhat unusual.  Note
here that we would have to test both the major and minor version numbers
to do this correctly.

I intend to replace that code with

  (static-if (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
    (electric-indent-local-mode (if c-electric-flag 1 0)))

..  (hash-if has been renamed static-if.)  It would be more work to
replace it with

  (when (or (> emacs-major-version 24)
            (and (= emacs-major-version 24)
	         (>= emacs-minor-version 4)))
    (electric-indent-local-mode (if c-electric-flag 1 0)))

, and that's not even taking into account the one-time effort to put
special handling into >, >=, <, <=, =, /= (?etc.) for
emacs-m\(aj\|in\)or-version.  I haven't looked into this in any detail,
but it might be quite a lot of work.

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

> If people would like other tests too, I have nothing against them.
> The issue is how to implement whatever tests we support.  If they can
> be done at compiler time, isn't this the better implementation?

static-if is a completely ordinary macro which is 10 lines long
(including doc string), and there's a new section in the elisp manual for
it.  Amending the evaluator and byte compiler for special handling for
emacs-m..or-version would be more than 10 lines.

There are currently just 45 occurrences of emacs-major-mode in our Lisp
sources, and most of these are comparisons with a decimal number.
Editing each occurrence by hand to use static-if would still be less work
than amending the evaluator and byte compiler for special handling.

We have just over 2000 occurrences of boundp and fboundp, some of which
will be used to isolate code to be evaluated only when the
variable/function is bound or not bound, as in the above CC Mode snippet.

> I guess I don't follow.  Why do you prefer `hash-if' rather
> than this simple compile-time syntax?  Why change the syntax rather
> than using the syntax we use now?

Because of the complexity of adding suitable special handling for
emacs-m..nor mode to the evaluator and byte compiler compared with the
simplicity of the new macro, and the relative ease of adapting existing
code.

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-04 10:50               ` Alan Mackenzie
@ 2023-09-04 11:02                 ` tomas
  2023-09-04 15:19                   ` Emanuel Berg
  2023-09-06  0:58                   ` Richard Stallman
  2023-09-06  0:58                 ` Richard Stallman
  1 sibling, 2 replies; 66+ messages in thread
From: tomas @ 2023-09-04 11:02 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Richard Stallman, ulm, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1159 bytes --]

On Mon, Sep 04, 2023 at 10:50:07AM +0000, Alan Mackenzie wrote:
> Hello, Richard.
> 
> On Sun, Sep 03, 2023 at 21:34:08 -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. ]]]

[...]

> >   > > How about making the byte compiler recognize the construct
>  
> >   > >  (if (< emacs-major-version NUMBER) ...)
> 
> >   > > and do this optimization on it?

[...]

>   (static-if (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
>     (electric-indent-local-mode (if c-electric-flag 1 0)))
> 
> ..  (hash-if has been renamed static-if.)  It would be more work to
> replace it with
> 
>   (when (or (> emacs-major-version 24)
>             (and (= emacs-major-version 24)
> 	         (>= emacs-minor-version 4)))
>     (electric-indent-local-mode (if c-electric-flag 1 0)))

Besides, a feature test is almost always better than a version test,
because it actually documents what the tester cares about.

Cheers
-- 
t

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-02 19:58               ` Alan Mackenzie
@ 2023-09-04 11:12                 ` Lynn Winebarger
  0 siblings, 0 replies; 66+ messages in thread
From: Lynn Winebarger @ 2023-09-04 11:12 UTC (permalink / raw)
  To: Alan Mackenzie
  Cc: Philip Kaludercic, Stefan Kangas, emacs-devel,
	Mattias Engdegård

[-- Attachment #1: Type: text/plain, Size: 268 bytes --]

On Sat, Sep 2, 2023, 3:58 PM Alan Mackenzie <acm@muc.de> wrote:

> Hello, Philip.
>
> > > +(defmacro static-if (condition then-form &rest else-forms)
>

Wouldn't "compile-when" be more harmonious with names like "eval-when-*"?
Or am I just too fond of wordplay?

Lynn

[-- Attachment #2: Type: text/html, Size: 876 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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
  1 sibling, 1 reply; 66+ messages in thread
From: Emanuel Berg @ 2023-09-04 15:19 UTC (permalink / raw)
  To: emacs-devel

tomas wrote:

> Besides, a feature test is almost always better than
> a version test, because it actually documents what the
> tester cares about.

And a feature can or can not be added to several versions.

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




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-04 15:19                   ` Emanuel Berg
@ 2023-09-04 18:57                     ` tomas
  0 siblings, 0 replies; 66+ messages in thread
From: tomas @ 2023-09-04 18:57 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 424 bytes --]

On Mon, Sep 04, 2023 at 05:19:14PM +0200, Emanuel Berg wrote:
> tomas wrote:
> 
> > Besides, a feature test is almost always better than
> > a version test, because it actually documents what the
> > tester cares about.
> 
> And a feature can or can not be added to several versions.

True: an older version might acquire a feature via some
package, who knows (although it could be a bad idea).

Cheers
-- 
t

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  2023-08-31  2:07         ` Richard Stallman
  2023-08-31  7:50           ` Alan Mackenzie
@ 2023-09-05  0:30           ` Richard Stallman
  2023-09-05  0:41             ` Emanuel Berg
                               ` (4 more replies)
  1 sibling, 5 replies; 66+ messages in thread
From: Richard Stallman @ 2023-09-05  0:30 UTC (permalink / raw)
  To: acm, ulm; +Cc: emacs-devel

[[[ 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. ]]]

  > How about making the byte compiler recognize the construct
 
  >  (if (< emacs-major-version NUMBER) ...)

  > and do this optimization on it?

People seem not to have considered this seriously, but I have not seen
any serious discussion of a drawback.  What flaw or drawback do people
see in it?  It should optimize the existing the existing code with no
change at all.  Isn't that just perfect?



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





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  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
                               ` (3 subsequent siblings)
  4 siblings, 1 reply; 66+ messages in thread
From: Emanuel Berg @ 2023-09-05  0:41 UTC (permalink / raw)
  To: emacs-devel

Richard Stallman wrote:

>> How about making the byte compiler recognize the construct
>>
>>  (if (< emacs-major-version NUMBER) ...)
>>
>> and do this optimization on it?
>
> People seem not to have considered this seriously, but
> I have not seen any serious discussion of a drawback.
> What flaw or drawback do people see in it? It should
> optimize the existing the existing code with no change at
> all. Isn't that just perfect?

Will it drop byte-compiler warnings as well from the part that
is dropped?

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




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  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-05  4:37             ` tomas
  2023-09-05  5:53               ` Ihor Radchenko
  2023-09-05 11:06             ` Adam Porter
                               ` (2 subsequent siblings)
  4 siblings, 1 reply; 66+ messages in thread
From: tomas @ 2023-09-05  4:37 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 943 bytes --]

On Mon, Sep 04, 2023 at 08:30:25PM -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. ]]]
> 
>   > How about making the byte compiler recognize the construct
>  
>   >  (if (< emacs-major-version NUMBER) ...)
> 
>   > and do this optimization on it?
> 
> People seem not to have considered this seriously, but I have not seen
> any serious discussion of a drawback.  What flaw or drawback do people
> see in it?  It should optimize the existing the existing code with no
> change at all.  Isn't that just perfect?

I did offer one: checking for a version number is actually a placeholder
for the feature your code cares about. Better be up-front in the test
and let the reader know what your code's needs are.

Cheers
-- 
t 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  2023-09-05  4:37             ` tomas
@ 2023-09-05  5:53               ` Ihor Radchenko
  2023-09-05  6:28                 ` tomas
  0 siblings, 1 reply; 66+ messages in thread
From: Ihor Radchenko @ 2023-09-05  5:53 UTC (permalink / raw)
  To: tomas; +Cc: emacs-devel

<tomas@tuxteam.de> writes:

> I did offer one: checking for a version number is actually a placeholder
> for the feature your code cares about. Better be up-front in the test
> and let the reader know what your code's needs are.

Not always. Sometimes, version check is necessary to work around bugs
that exist in older Emacs.

Example:

(defun org-string-width (string &optional pixels)
  "Return width of STRING when displayed in the current buffer.
Return width in pixels when PIXELS is non-nil."
  (if (and (version< emacs-version "28") (not pixels))
      ;; FIXME: Fallback to old limited version, because
      ;; `window-pixel-width' is buggy in older Emacs.
      (org--string-width-1 string)


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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  2023-09-05  5:53               ` Ihor Radchenko
@ 2023-09-05  6:28                 ` tomas
  0 siblings, 0 replies; 66+ messages in thread
From: tomas @ 2023-09-05  6:28 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 815 bytes --]

On Tue, Sep 05, 2023 at 05:53:30AM +0000, Ihor Radchenko wrote:
> <tomas@tuxteam.de> writes:
> 
> > I did offer one: checking for a version number is actually a placeholder
> > for the feature your code cares about. Better be up-front in the test
> > and let the reader know what your code's needs are.
> 
> Not always. Sometimes, version check is necessary to work around bugs
> that exist in older Emacs.

I think I said in my original post "almost always". All generalisations
suck ;-)

But even in your example's case I'd try to come up with a test which
discriminates between the behaviours.

Now this is engineering and everything is a tradeoff. Perhaps this test
is prohibitive, perhaps it can't be done at compile time and so on.

So I do agree with your "not always".

Cheers
-- 
t

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-08-28 21:46       ` Alan Mackenzie
  2023-08-31  2:07         ` Richard Stallman
@ 2023-09-05  8:14         ` Ulrich Mueller
  1 sibling, 0 replies; 66+ messages in thread
From: Ulrich Mueller @ 2023-09-05  8:14 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

>>>>> On Mon, 28 Aug 2023, Alan Mackenzie wrote:

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

I've just tested with current master. Byte-compiling this:

   (static-if (> emacs-major-version 24)
       (message "new emacs")
     (message "old emacs"))

and this:

   (if (eval-when-compile (> emacs-major-version 24))
       (message "new emacs")
     (message "old emacs"))

results in identical byte code.

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

Sorry, I cannot reproduce this problem. Could you give an example?



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  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-05  4:37             ` tomas
@ 2023-09-05 11:06             ` Adam Porter
  2023-09-05 11:26             ` Lynn Winebarger
  2023-09-05 14:11             ` Alan Mackenzie
  4 siblings, 0 replies; 66+ messages in thread
From: Adam Porter @ 2023-09-05 11:06 UTC (permalink / raw)
  To: rms; +Cc: acm, emacs-devel, ulm

>   > How about making the byte compiler recognize the construct
>  
>   >  (if (< emacs-major-version NUMBER) ...)
> 
>   > and do this optimization on it?
> 
> People seem not to have considered this seriously, but I have not seen
> any serious discussion of a drawback.  What flaw or drawback do people
> see in it?  It should optimize the existing the existing code with no
> change at all.  Isn't that just perfect?

Maybe I'm misunderstanding something, but while that idea does seem 
elegant, a potential drawback of that idea would seem to be that 
byte-compiled code would need to be recompiled when the user's Emacs 
version changed in a relevant way, while checking at runtime would mean 
that it would always behave correctly.

It's my impression that most Emacs users don't know about byte-compiling 
packages, so when encountering such a problem, most of them wouldn't 
know to "M-x package-recompile" to try to solve it.  They'd probably end 
up posting a message somewhere asking for help, or even making a false 
bug report to a package author.

Having said that, am I wrong in thinking that this STATIC-IF suggestion 
would suffer from the same problem?  Here's the scenario I'm imagining:

1.  User is running Emacs vN.

2.  User installs package P at vM.

3.  Emacs vN+1 is released.

4.  Package P is updated to conditionally use features from Emacs vN+1,
and the package is released at vM+1.

5.  User installs package P at vM+1 while still using Emacs vN.  The 
package is byte-compiled for Emacs vN and so compiles out the optional 
support for features available on Emacs vN+1.

6.  User upgrades Emacs to vN+1 and starts it.

7.  User expects package P's support for the new features to be 
available, but it's not, and there's no apparent reason why.

8.  User files a bug report on package P.

9.  Package P's author is confused and asks the user to reinstall the 
package.

10.  User does so and it works.  Everyone shrugs.

11.  At some later date, the package author realizes what happened, 
perhaps from reading a thread on emacs-devel, and the next time a user 
reports the same problem (likely to happen for a year or two, given how 
long Emacs versions remain in use), he tells the user to "M-x 
package-recompile" it.

Again, maybe I'm missing something obvious, but that scenario seems very 
likely to me, so I'm not sure that byte-compiling features conditionally 
on the version of Emacs used to compile the file is a great idea. 
Runtime checks seem much more robust.



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  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
                               ` (2 preceding siblings ...)
  2023-09-05 11:06             ` Adam Porter
@ 2023-09-05 11:26             ` Lynn Winebarger
  2023-09-05 14:11             ` Alan Mackenzie
  4 siblings, 0 replies; 66+ messages in thread
From: Lynn Winebarger @ 2023-09-05 11:26 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Alan Mackenzie, ulm, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 998 bytes --]

On Mon, Sep 4, 2023, 8:30 PM Richard Stallman <rms@gnu.org> 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. ]]]
>
>   > How about making the byte compiler recognize the construct
>
>   >  (if (< emacs-major-version NUMBER) ...)
>
>   > and do this optimization on it?
>
> People seem not to have considered this seriously, but I have not seen
> any serious discussion of a drawback.  What flaw or drawback do people
> see in it?  It should optimize the existing the existing code with no
> change at all.  Isn't that just perfect?
>


Since byte-compiled files are not versioned, emacs-major-version is not
really a constant, so constant-folding isn't correct.
For example, loading a file in version 29 that was byte-compiled by version
28 (or earlier) may not be the same as byte-compiling the file with version
29.

Lynn

[-- Attachment #2: Type: text/html, Size: 1698 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  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
                               ` (3 preceding siblings ...)
  2023-09-05 11:26             ` Lynn Winebarger
@ 2023-09-05 14:11             ` Alan Mackenzie
  2023-09-08  1:01               ` Richard Stallman
  4 siblings, 1 reply; 66+ messages in thread
From: Alan Mackenzie @ 2023-09-05 14:11 UTC (permalink / raw)
  To: Richard Stallman; +Cc: ulm, emacs-devel

Hello, Richard.

On Mon, Sep 04, 2023 at 20:30:25 -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. ]]]

>   > How about making the byte compiler recognize the construct
 
>   >  (if (< emacs-major-version NUMBER) ...)

>   > and do this optimization on it?

> People seem not to have considered this seriously, ....

It was actually the first thing I considered when the original problem
occurred to me.  We have a similar optimisation in place for (featurep
xemacs).  But then, the number of ways emacs-major-version (to say
nothing of emacs-minor-version) can be used is large (starting with <,
<=, >, >=, =, /=, eq, eql, equal, and extending to predicates involving
e-minor-v), that it would be at least somewhat difficult to apply in
practice.

> .... but I have not seen any serious discussion of a drawback.

I outlined some drawbacks in my post of yesterday evening (Monday
2022-09-04), European time.

> What flaw or drawback do people see in it?

The above.  Plus, some (possibly most) of the predicates we want to
optimise out are expressed in terms of present/absent features rather
than numeric version numbers.  There are  just 45 occurrences of
emacs-major-version in the Lisp sources, over 2000 occurrences of boundp
and fboundp.  We could convert (some of) those 45 to use static-if in
less time than it would take to amend the interpreter and byte-compiler
to handler emacs-major-version specially.

> It should optimize the existing the existing code with no change at
> all.  Isn't that just perfect?

Sadly, no it's not.  It would only do part of the job which is to be
done.  It would make some parts of Emacs more complicated.


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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-04 10:50               ` Alan Mackenzie
  2023-09-04 11:02                 ` tomas
@ 2023-09-06  0:58                 ` Richard Stallman
  2023-09-06  7:28                   ` Andreas Schwab
  2023-09-06  9:56                   ` Alan Mackenzie
  1 sibling, 2 replies; 66+ messages in thread
From: Richard Stallman @ 2023-09-06  0:58 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ulm, emacs-devel

[[[ 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. ]]]

  > For example, in CC Mode there is a chunk of code looking like ....

  >   (when (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
  >     (electric-indent-local-mode (if c-electric-flag 1 0)))

  > , and there are quite a few instances like it.  Here, there is a comment
  > about which versions are relevant, but that is somewhat unusual.  Note
  > here that we would have to test both the major and minor version numbers
  > to do this correctly.

  > I intend to replace that code with

  >   (static-if (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
  >     (electric-indent-local-mode (if c-electric-flag 1 0)))

  > ..  (hash-if has been renamed static-if.)  It would be more work to
  > replace it with

  >   (when (or (> emacs-major-version 24)
  >             (and (= emacs-major-version 24)
  > 	         (>= emacs-minor-version 4)))
  >     (electric-indent-local-mode (if c-electric-flag 1 0)))

If you want to have a conditional about version mumbers,
I think that is the right way to write it.

Or, if you want to keep the condition about the availability of
electric-indent-local-mode, how about keeping the code unchanged

  >   (when (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
  >     (electric-indent-local-mode (if c-electric-flag 1 0)))

and inform the byte compiler that (fboundp 'electric-indent-local-mode)
can be optimized based on the Emacs cersion?  This way you won't need
to change the source code, and we will get the ideal results,

  > static-if is a completely ordinary macro which is 10 lines long
  > (including doc string), and there's a new section in the elisp manual for
  > it.

I think the simplicity of the source code as it will be
counts for more than the simplicity of a new macro
which, with my approach, we don't need o add.







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





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-04 11:02                 ` tomas
  2023-09-04 15:19                   ` Emanuel Berg
@ 2023-09-06  0:58                   ` Richard Stallman
  1 sibling, 0 replies; 66+ messages in thread
From: Richard Stallman @ 2023-09-06  0:58 UTC (permalink / raw)
  To: tomas; +Cc: acm, ulm, emacs-devel

[[[ 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. ]]]

  > Besides, a feature test is almost always better than a version test,
  > because it actually documents what the tester cares about.

Indeed it is ofter better, but why are you saying that to me?
I did not propose to replace a version test with a feature test,
or vice versa.

I proposed to handle existing version tests more efficiently without
any change in the source code.  Others had proposed (or so it
appeared) to change the syntax of some version tests, to optimize
them, and I suggested we could optimize them better without changing
their syntax at all.

If people propose to change some version tests to feature tests, I'm
not necessarily against that.  It might be a good idea.  But that
seems to be a different question.

If we consider that, we need to look for the best way to handle these
new feature tests.

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





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  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
  1 sibling, 1 reply; 66+ messages in thread
From: Andreas Schwab @ 2023-09-06  7:28 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Alan Mackenzie, ulm, emacs-devel

On Sep 05 2023, Richard Stallman wrote:

>   > ..  (hash-if has been renamed static-if.)  It would be more work to
>   > replace it with
>
>   >   (when (or (> emacs-major-version 24)
>   >             (and (= emacs-major-version 24)
>   > 	         (>= emacs-minor-version 4)))
>   >     (electric-indent-local-mode (if c-electric-flag 1 0)))
>
> If you want to have a conditional about version mumbers,
> I think that is the right way to write it.

We also have (version<= "24.4" emacs-version).

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-06  7:28                   ` Andreas Schwab
@ 2023-09-06  9:31                     ` Alan Mackenzie
  0 siblings, 0 replies; 66+ messages in thread
From: Alan Mackenzie @ 2023-09-06  9:31 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Richard Stallman, ulm, emacs-devel

Hello, Andreas.

On Wed, Sep 06, 2023 at 09:28:35 +0200, Andreas Schwab wrote:
> On Sep 05 2023, Richard Stallman wrote:

> >   > ..  (hash-if has been renamed static-if.)  It would be more work to
> >   > replace it with

> >   >   (when (or (> emacs-major-version 24)
> >   >             (and (= emacs-major-version 24)
> >   > 	         (>= emacs-minor-version 4)))
> >   >     (electric-indent-local-mode (if c-electric-flag 1 0)))

> > If you want to have a conditional about version mumbers,
> > I think that is the right way to write it.

> We also have (version<= "24.4" emacs-version).

Thanks!  I didn't know about that.

> -- 
> Andreas Schwab, SUSE Labs, schwab@suse.de
> GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
> "And now for something completely different."

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-06  0:58                 ` Richard Stallman
  2023-09-06  7:28                   ` Andreas Schwab
@ 2023-09-06  9:56                   ` Alan Mackenzie
  2023-09-09  0:39                     ` Richard Stallman
  1 sibling, 1 reply; 66+ messages in thread
From: Alan Mackenzie @ 2023-09-06  9:56 UTC (permalink / raw)
  To: Richard Stallman; +Cc: ulm, emacs-devel

Hello, Richard.

On Tue, Sep 05, 2023 at 20:58:38 -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. ]]]

>   > For example, in CC Mode there is a chunk of code looking like ....

>   >   (when (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
>   >     (electric-indent-local-mode (if c-electric-flag 1 0)))

>   > , and there are quite a few instances like it.  Here, there is a comment
>   > about which versions are relevant, but that is somewhat unusual.  Note
>   > here that we would have to test both the major and minor version numbers
>   > to do this correctly.

>   > I intend to replace that code with

>   >   (static-if (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
>   >     (electric-indent-local-mode (if c-electric-flag 1 0)))

>   > ..  (hash-if has been renamed static-if.)  It would be more work to
>   > replace it with

>   >   (when (or (> emacs-major-version 24)
>   >             (and (= emacs-major-version 24)
>   > 	         (>= emacs-minor-version 4)))
>   >     (electric-indent-local-mode (if c-electric-flag 1 0)))

> If you want to have a conditional about version mumbers,
> I think that is the right way to write it.

Originally, I wasn't really thinking about version numbers being the
prime use case, but it was easy to use them as an example to get the
discussion going.

> Or, if you want to keep the condition about the availability of
> electric-indent-local-mode, how about keeping the code unchanged

>   >   (when (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
>   >     (electric-indent-local-mode (if c-electric-flag 1 0)))

> and inform the byte compiler that (fboundp 'electric-indent-local-mode)
> can be optimized based on the Emacs version?  This way you won't need
> to change the source code, and we will get the ideal results.

I don't know how to do this.  Early on in the thread, Ulrich Müller
suggested using

    (when (eval-when-compile (fboundp 'electric-indent-local-mode))
       (electric-indent-local-mode (if c-electric-flag 1 0)))

, in which the conditional gets optimised away at compile time.  But
that's still a change in the source code.

>   > static-if is a completely ordinary macro which is 10 lines long
>   > (including doc string), and there's a new section in the elisp manual for
>   > it.

> I think the simplicity of the source code as it will be
> counts for more than the simplicity of a new macro
> which, with my approach, we don't need to add.

We must also take into account the additional complexity of the defmacro
and defun macros (etc.) and the byte compiler to handle the new special
case.  As I've already said, there are just 45 occurrences of
emacs-major-version in the Lisp sources.

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  2023-09-05 14:11             ` Alan Mackenzie
@ 2023-09-08  1:01               ` Richard Stallman
  2023-09-08  2:45                 ` Po Lu
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Stallman @ 2023-09-08  1:01 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ulm, emacs-devel

[[[ 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. ]]]

If you want to convert most of the existing version conditions to
feature tests, in general I don't object.

But there is one thing to watch out for: in each instance, it can
happen that a feature test is kludgy and a version test is cleaner.
It can also happen that a version test is kludgy and a feature test is
cleaner.  So it could happen that, after converting 40 version tests
to feature tests that are natural, there will be 5 remaining version
tests that are better left as version tests.

Or there might be 10 such, or none such.  It might be better to leave
a few of them as version tests while converting the rest.

Optimizing these tests to operate at compile time is a separate issue.
Please DON'T introduce a new construct `static-if' -- instead please
make the compiler optimize the constructs that are already in the
code.

That can be done for feature tests, or for version tests, or for both.
It won't be difficult.

Why link these two issues?  Your last message still presumes using
`static-if' but it shows no advantage in that choice.  For instance,

  > It was actually the first thing I considered when the original problem
  > occurred to me.  We have a similar optimisation in place for (featurep
  > xemacs).  But then, the number of ways emacs-major-version (to say
  > nothing of emacs-minor-version) can be used is large (starting with <,
  > <=, >, >=, =, /=, eq, eql, equal, and extending to predicates involving
  > e-minor-v), that it would be at least somewhat difficult to apply in
  > practice.

I don't see an argument there for `static-if' instead of handling `if'
at compile time (assuming the actual conditional is the same either way,
which it can be).  Likewise, here

  >   We could convert (some of) those 45 to use static-if in
  > less time than it would take to amend the interpreter and byte-compiler
  > to handler emacs-major-version specially.

Maybe so, but the latter would be cleaner.  Also, if some if those 45
are converted to feature tests, this issue will be smaller, If only 5
version tests remain, the number of ways such tests are expressed will
be at most 5, and they could easily be reduced to 1 or 2.





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





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  2023-09-08  1:01               ` Richard Stallman
@ 2023-09-08  2:45                 ` Po Lu
  2023-09-10  0:24                   ` Richard Stallman
  0 siblings, 1 reply; 66+ messages in thread
From: Po Lu @ 2023-09-08  2:45 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Alan Mackenzie, ulm, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Optimizing these tests to operate at compile time is a separate issue.
> Please DON'T introduce a new construct `static-if' -- instead please
> make the compiler optimize the constructs that are already in the
> code.

That's already a fait accompli: static-if was introduced several days
ago.



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  2023-09-05  0:41             ` Emanuel Berg
@ 2023-09-08 17:54               ` Emanuel Berg
  0 siblings, 0 replies; 66+ messages in thread
From: Emanuel Berg @ 2023-09-08 17:54 UTC (permalink / raw)
  To: emacs-devel

> Will it drop byte-compiler warnings as well from the part
> that is dropped?

They are dropped,

(static-if (< 1 2)
    (no-function-one) ; warning here, ‘no-function-one’ not defined
  (no-function-two) ) ; but no warning here

GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, cairo version 1.16.0)
of 2023-09-08 [commit a2f977d94e0356c7414876e988adedd2ab7b52f2]

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




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-06  9:56                   ` Alan Mackenzie
@ 2023-09-09  0:39                     ` Richard Stallman
  2023-09-09 10:32                       ` Ihor Radchenko
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Stallman @ 2023-09-09  0:39 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ulm, emacs-devel

[[[ 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. ]]]

  > > Or, if you want to keep the condition about the availability of
  > > electric-indent-local-mode, how about keeping the code unchanged

  > >   >   (when (fboundp 'electric-indent-local-mode) ; Emacs 24.4 or later.
  > >   >     (electric-indent-local-mode (if c-electric-flag 1 0)))

  > > and inform the byte compiler that (fboundp 'electric-indent-local-mode)
  > > can be optimized based on the Emacs version?  This way you won't need
  > > to change the source code, and we will get the ideal results.

  > I don't know how to do this.  Early on in the thread, Ulrich Müller
  > suggested using

We can make the byte compiler recognize any pattern of code
and treat it specially.  It has two sets of special
patterns: those for inside function definitions (being compiled in
the strict sense of the word), and those for top level.

A pattern for top level could recognize patterns like

   (if (fboundp ...) ...)  and  (if (not (fboundp ...)) ...)

and do whatever the proposed `static-if' function would have done.

Why not?

You spoke of "the additional complexity of the defmacro and defun
macros".  Could you please say concretely what that refers to, because
I don't see it.

  > Originally, I wasn't really thinking about version numbers being the
  > prime use case, but it was easy to use them as an example to get the
  > discussion going.

I think I misunderstood that point, but it's cleared up now.

I am not arguing for or against switching between feature tests
and version tests.  The approach I am suggesting should work for both.


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





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-09  0:39                     ` Richard Stallman
@ 2023-09-09 10:32                       ` Ihor Radchenko
  2023-09-10  0:22                         ` Richard Stallman
  0 siblings, 1 reply; 66+ messages in thread
From: Ihor Radchenko @ 2023-09-09 10:32 UTC (permalink / raw)
  To: rms; +Cc: Alan Mackenzie, ulm, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> We can make the byte compiler recognize any pattern of code
> and treat it specially.  It has two sets of special
> patterns: those for inside function definitions (being compiled in
> the strict sense of the word), and those for top level.
>
> A pattern for top level could recognize patterns like
>
>    (if (fboundp ...) ...)  and  (if (not (fboundp ...)) ...)
>
> and do whatever the proposed `static-if' function would have done.
>
> Why not?

Because there are cases when `fboundp' should be checked at runtime.
For example, some parts of Org use `fboundp' to check if certain
third-party optional dependencies are loaded. If `fboundp' is resolved
at compile time, such checks will be broken.

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-09 10:32                       ` Ihor Radchenko
@ 2023-09-10  0:22                         ` Richard Stallman
  2023-09-10  8:36                           ` Ihor Radchenko
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Stallman @ 2023-09-10  0:22 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: acm, ulm, emacs-devel

[[[ 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. ]]]

  > Because there are cases when `fboundp' should be checked at runtime.
  > For example, some parts of Org use `fboundp' to check if certain
  > third-party optional dependencies are loaded. If `fboundp' is resolved
  > at compile time, such checks will be broken.

I am confident there is a convenient way to distinguish the cases
where you want run-time tests from those where you would like
compile-time tests.  But I can't try to look for it until I see
what the former cases look like.  Can you show me an example?

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





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why have a #if .... #else .... #endif construct in Emacs Lisp, when we could make the existing code DTRT unchanged?
  2023-09-08  2:45                 ` Po Lu
@ 2023-09-10  0:24                   ` Richard Stallman
  0 siblings, 0 replies; 66+ messages in thread
From: Richard Stallman @ 2023-09-10  0:24 UTC (permalink / raw)
  To: Po Lu; +Cc: acm, ulm, emacs-devel

[[[ 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. ]]]

  > That's already a fait accompli: static-if was introduced several days
  > ago.

If the compiler optimization I proposed and the static-if function
give the same results, the compiler optimization is cleaner.
We should use that rather than change the code to use static-if.

If they do NOT give the same results, would someone please explain why
not?

Adam Porter <adam@alphapapa.net> wrote:

  > Maybe I'm misunderstanding something, but while that idea does seem 
  > elegant, a potential drawback of that idea would seem to be that 
  > byte-compiled code would need to be recompiled when the user's Emacs 
  > version changed in a relevant way, while checking at runtime would mean 
  > that it would always behave correctly.

If the package is used with different Emacs versions and not compiled
for each one, then it needs to test the version condition, or the
feature condition, each time it is loaded.

This optimization seems intended to optimize the condition by testing it
at compile time.  That presumes it will be compiled for a specific Emacs.
So I assumed that was the scenario.

We can't have it both ways.


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





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-10  0:22                         ` Richard Stallman
@ 2023-09-10  8:36                           ` Ihor Radchenko
  2023-09-13 23:53                             ` Richard Stallman
  0 siblings, 1 reply; 66+ messages in thread
From: Ihor Radchenko @ 2023-09-10  8:36 UTC (permalink / raw)
  To: rms; +Cc: acm, ulm, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > Because there are cases when `fboundp' should be checked at runtime.
>   > For example, some parts of Org use `fboundp' to check if certain
>   > third-party optional dependencies are loaded. If `fboundp' is resolved
>   > at compile time, such checks will be broken.
>
> I am confident there is a convenient way to distinguish the cases
> where you want run-time tests from those where you would like
> compile-time tests.  But I can't try to look for it until I see
> what the former cases look like.  Can you show me an example?

Org mode uses `fboundp' check to fontify arbitrary source blocks:

#+begin_src language
...
#+end_src

The corresponding code does the following:

(defun org-src-font-lock-fontify-block (lang start end)
  "Fontify code block between START and END using LANG's syntax.
This function is called by Emacs' automatic fontification, as long
as `org-src-fontify-natively' is non-nil."
...
    (let ((lang-mode (org-src-get-lang-mode lang)))
      (when (fboundp lang-mode)
      <fontify using LANG-MODE's native fontification>

This cannot be optimized on compile time because we cannot know in
advance which languages are to be fontified by user.

Another example is Org mode optional inlinetask library "org-inlinetask".
When the library is loaded, certain constructs are parsed differently in
Org files:

(defun org-back-to-heading (&optional invisible-ok)
  "Go back to beginning of heading or inlinetask."
  (forward-line 0)
  (or (and (org-at-heading-p (not invisible-ok))
           (not (and (featurep 'org-inlinetask)
                   (fboundp 'org-inlinetask-end-p) ; <----
                   (org-inlinetask-end-p))))

This must also be a runtime check, because it is up to the users whether
this optional library is to be used or not.

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-10  8:36                           ` Ihor Radchenko
@ 2023-09-13 23:53                             ` Richard Stallman
  2023-09-20 12:59                               ` Ihor Radchenko
  0 siblings, 1 reply; 66+ messages in thread
From: Richard Stallman @ 2023-09-13 23:53 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: acm, ulm, emacs-devel

[[[ 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. ]]]

  > Org mode uses `fboundp' check to fontify arbitrary source blocks:

  > #+begin_src language
  > ...
  > #+end_src

  > The corresponding code does the following:

  > (defun org-src-font-lock-fontify-block (lang start end)
  >   "Fontify code block between START and END using LANG's syntax.
  > This function is called by Emacs' automatic fontification, as long
  > as `org-src-fontify-natively' is non-nil."
  > ...
  >     (let ((lang-mode (org-src-get-lang-mode lang)))
  >       (when (fboundp lang-mode)
  >       <fontify using LANG-MODE's native fontification>

We may be talking about different kincs of cases.

As I understand it, the proposal was to handle at compile time
certain conditionals at _top-level_ in the source file being compiled.
Things like

(if (fboundp 'whatever)
  ...conditional-code...)

However, what you've shown is a conditional inside a function definition
that is part of org-mode -- right?

The proposal I think we are discussing would have no effect at all on
cases like that.  So this example would get the unchanged curent
behavior, just as you asked for.


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





^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Why shouldn't we have a #if .... #else .... #endif construct in Emacs Lisp?
  2023-09-13 23:53                             ` Richard Stallman
@ 2023-09-20 12:59                               ` Ihor Radchenko
  0 siblings, 0 replies; 66+ messages in thread
From: Ihor Radchenko @ 2023-09-20 12:59 UTC (permalink / raw)
  To: rms; +Cc: acm, ulm, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> As I understand it, the proposal was to handle at compile time
> certain conditionals at _top-level_ in the source file being compiled.
> Things like
>
> (if (fboundp 'whatever)
>   ...conditional-code...)
>
> However, what you've shown is a conditional inside a function definition
> that is part of org-mode -- right?

You are right. Though we also have top-level instances of `fboundp' in
Org that should not be optimized away during compile time.

In particular, ol-w3m.el in Org has

(when (and (boundp 'w3m-mode-map)
           (keymapp w3m-mode-map))
  (define-key w3m-mode-map "\C-c\C-x\M-w" 'org-w3m-copy-for-org-mode)
  (define-key w3m-mode-map "\C-c\C-x\C-w" 'org-w3m-copy-for-org-mode))

w3m-mode-map is only available when w3m package is installed, which can
happen after Org mode is compiled.

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



^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2023-09-20 12:59 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).