[erlang-questions] Fourth draft of EEP 44 - Additional preprocessor directives

Richard A. O'Keefe ok@REDACTED
Mon Nov 2 04:13:38 CET 2015


I am still unhappy that we cannot conditionally
select *clauses*.  I do know that it is possible to do

-if...
-define(WANTED, true).
-else.
-define(WANTED, false).
-endif.
...
f(...)
f(...) when ?WANTED
f(...)

*But* as EEP 44 reminds us,

"There is one thing a preprocessor, and only a preprocessor
 can do: skip code that is not syntactically correct
 (for example, code that uses the map syntax)."

In fact this proposal *still* does not give us a way to
skip one or more clauses that *would* be syntactically
incorrect in some context.

There is a very simple change to Erlang that would make
this possible:  allow '.' between function clauses as
well as ';'.

That would also enable us to paste a function together
out of pieces held in separate files:

% Define f/3
-include("old_f.hrl").
-include("new_f.hrl").


That aside, I think this draft is pretty good.

I don't quite buy the argument against 'supported':

   Perhaps. It seems that for this to work the list
   of supported feature names accepted by supported
   must be carefully maintained and documented for each
   release.  The users must then look up the appropriate
   feature name to use. It may also not be obvious how
   to name minor changes to the type specification
   syntax or to the language itself. The resulting code
   may not be any easier to understand than a test
   against a release number.

Considering the needs of the *writer*, ?OTP_RELEASE is
easier than 'supported'.  The list of features supported
by each release "must be carefully maintained and
documented for each release" *anyway*.

But considering the needs of the *maintainer*, if I
see just
 -if(OTP_RELEASE > 20).
then I have no clue about *why* that test is there.
I have to search the documentation (and let us hope tha/*fenv
there _is_ a documentation file listing all and only the
things that you might use OTP_RELEASE for) and then guess
which of perhaps ten reasons is the correct one.

Amongst other things, since features do sometimes go
away, I am left with no clue about whether I ought to
replace that by
 -if(OTP_RELEASE > 20 andalso OTP_RELEASE < 25).

I think I can confidently say that an -if using names
*will* be easier to understand than one using OTP_RELEASE.

I do accept that 'supported' is something that can well be
added in a later EEP, and I would not take the clunkiness
of OTP_RELEASE as a show-stopper.  But the documentation
should insist that anyone using OTP_RELEASE write an
explicit comment clearly stating what they are really
testing for.

Let me give you an analogy.  In the support code for my
Smalltalk system, there are tests for __APPLE__, __OpenBSD__,
__linux, and __Solaris.  I'll spare you the details, but

- common functions in different headers or even lacking headers
- common features requiring DIFFERENT feature-test macros to
  get them
- no better way to discover what you need to do than testing
  which system it is.

As a result, #ifdef __APPLE__ could really be asking at least
four different questions.  It's usually pretty clear which,
but I see I'm going to have to improve my internal documentation.

Yes, I know that this is exactly the kind of thing that
configure and friends exist to solve, but if you're trying to
keep GNU stuff out of your program, what can you do?

I'm saying that using OTP_RELEASE is just as confusing as
using __APPLE__.

There is a way to test if a *header* exists (is_header/1),
which looks in the header search path.
There is a way to test if a (compiled) *module* exists
(is_module/1), which looks in the module search path.
I am convinced that these are good ideas.  If only C had them!

But there is no way to test if a *data file* exists.






More information about the erlang-questions mailing list