Suggestion to add ifndef builtin macro

Daniel Goldman <[email protected]> Thu, 15 May 2014 13:13:43 -0700
Newsgroups gmane.comp.gnu.m4.general
Message-ID <[email protected]>
Hi,

I would like to suggest the small change to add an m4_ifndef builtin 
macro to some future version of m4.

In case any question, m4_ifndef would be exactly the same as m4_ifdef, 
with the logic reversed. Modifying the manual text:

***************

Builtin: ifndef (name, string-1, [string-2]

If name is NOT defined as a macro, ifndef expands to string-1, otherwise 
to string-2. If string-2 is omitted, it is taken to be the empty string 
(according to the normal rules).

The macro ifndef is recognized only with parameters.

**********

Reason #1 I suggest adding m4_ifndef is for better communication, to 
make the language easier to express the logic. Perhaps a lot of m4 usage 
is obscure, but I don't consider that a virtue. I would argue that:

m4_ifndef(`MACRO_1', `MACRO_1' NOT defined)

is clearer than:

m4_ifdef(`MACRO_1', , `MACRO_1' NOT defined)

because it is more clear that we are testing for "not defined", and 
having the separate macro makes it easier to scan the code for 
particular logical patterns.

*********

Reason #2 I suggest adding is because since it's so closely related to 
m4_ifdef, my guess is that it would not be that hard to code m4_ifndef.

**********

Reason #3 I suggest adding is because as a sample of one, if m4_ifndef 
was available, I would use it. :) So at least one m4 user would find it 
beneficial.

********

Reason #1 in favor of NOT adding is because m4_ifdef is adequate to do 
the logical operations. To my understanding the following two macros are 
100% equivalent:

m4_ifdef(`MACRO_1', `MACRO_1' defined, `MACRO_1' NOT defined)
m4_ifndef(`MACRO_1', `MACRO_1' NOT defined, `MACRO_1' defined)

But the single argument form seems more clear with m4_ifndef. I like 
having both symmetric forms:

m4_ifdef(`MACRO_1', `MACRO_1' defined)
m4_ifndef(`MACRO_1', `MACRO_1' NOT defined)

***********

Reason #2 in favor of NOT adding is there is probably some way to do 
this reliably with a composite macro. Scanning through some past posts, 
I see references to ifndef, so maybe this is already done. Here is my 
best attempt, which seems to work correctly, please correct my logic if 
some flaw:

$ cat ifndef-02.m4
m4_define(`m4_ifndef', `m4_ifdef(`$1', `$3', `$2')')
m4_define(`MACRO_1')
m4_ifdef(`MACRO_1', ``MACRO_1' defined')
m4_ifdef(`MACRO_1', ``MACRO_1' defined', ``MACRO_1' NOT defined')
m4_ifdef(`MACRO_2', ``MACRO_2' defined')
m4_ifdef(`MACRO_2', ``MACRO_2' defined', ``MACRO_2' NOT defined')
m4_ifndef(`MACRO_1', ``MACRO_1' NOT defined')
m4_ifndef(`MACRO_1', ``MACRO_1' NOT defined', ``MACRO_1' defined')
m4_ifndef(`MACRO_2', ``MACRO_2' NOT defined')
m4_ifndef(`MACRO_2', ``MACRO_2' NOT defined', ``MACRO_2' defined')

$ m4 -P ifndef-02.m4


MACRO_1 defined
MACRO_1 defined

MACRO_2 NOT defined

MACRO_1 defined
MACRO_2 NOT defined
MACRO_2 NOT defined

But even if a composite m4_ifndef macro words, it seems logical and 
useful to include as a builtin, as a standard part of the language.

Thanks,
Daniel