On 2024-04-05, Janis Papanagnou <janis_papanagnou+
ng@hotmail.com> wrote:
On 05.04.2024 01:29, Lawrence D'Oliveiro wrote:
On 4 Apr 2024 11:20:48 GMT, Stefan Ram wrote:
And let me tell you, when you start getting into that kind of nested
stuff with not parentheses in view, even the "?:" notation can start
looking pretty darn mysterious to some folks.
This is where indentation helps. E.g.
a =
b ?
c ? d : e
: f ?
g ? h : i
: j;
>
Indentation generally helps. In above code (in my book) it's not
that clear [from the indentation], e.g. where the last ':' 'else'
belongs to. So I'd have lined the colons up with the respective
'?'. (YMMV.)
>
Not all languages differentiate (per syntax) a conditional command
from a conditional expression. Here are the two forms supported by
Algol for both, statements and expressions (here the examples are
both depicted for expressions only)
>
a :=
( b | ( c | d | e )
| ( f | ( g | h | i )
| j ) );
>
The parenthesis are not used for grouping, but are the alternative
form for IF/THEN/ELSE/FI
>
a := IF b
THEN
IF c THEN d ELSE e FI
ELSE
IF f THEN
IF g THEN h ELSE i FI
ELSE j FI
FI
>
Pick your choice depending on the case (or taste).
#define XCAT(A, B) A ## B
#define CAT(A, B) XCAT(A, B)
#define IF(A, B, C) ((A) ? (B) : (C))
#define COND_2(cond, then, ...) IF(cond, then, 0)
#define COND_4(cond, then, ...) IF(cond, then, COND_2(__VA_ARGS__))
#define COND_6(cond, then, ...) IF(cond, then, COND_4(__VA_ARGS__))
#define COND_8(cond, then, ...) IF(cond, then, COND_6(__VA_ARGS__))
#define COND_1(...) {syntax error}
#define COND_3(...) {syntax error}
#define COND_5(...) {syntax error}
#define COND_7(...) {syntax error}
#define COUNT_ARGS(...) COUNT_ARGS_IMPL(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define COUNT_ARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define COND(...) CAT(COND_, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
Now we can do:
COND(b, ...,
f, ...
1, j)
filling in the ...:
COND(b, IF(c, d, e),
f, IF(g, h, i),
1, j)
The GNU preprocessor gives me this:
((b) ? (((c) ? (d) : (e))) : (((f) ? (((g) ? (h) : (i))) : (((1) ? (j) : (0))))))
which looks correct.
The code is readable now, and importantly, my editor can format it. If I
start adding line breaks, it's indented right. If I turn it into this:
COND(b, IF(c, d, e),
f, IF(g, h, i),
1, j)
then highlight it in Vim and hit =, it gets put back the way it was.
If I add line breaks into the IFs, they get automatically indented
right, just using Vim's support for basic C formatting of macro/function
calls:
cond(b, IF(c,
d,
e),
f, IF(g,
h,
i),
1, j)
Compared to wrestling with five ways of formatting the the ill-conceived
?: syntax, it's a complete no brainer.
Here is a version where the cond pairs have to be parenthesized.
We can lose the even/odd argument count handling, and might as well
extend to up to 8 clauses:
#define IF(A, B, C) ((A) ? (B) : (C))
#define XCAT(A, B) A ## B
#define CAT(A, B) XCAT(A, B)
#define COND_PAIR(pair, rest) IF(COND_COND pair, COND_THEN pair, rest)
#define COND_COND(cond, then) cond
#define COND_THEN(cond, then) then
#define COND_1(pair, ...) COND_PAIR(pair, 0)
#define COND_2(pair, ...) COND_PAIR(pair, COND_1(__VA_ARGS__))
#define COND_3(pair, ...) COND_PAIR(pair, COND_2(__VA_ARGS__))
#define COND_4(pair, ...) COND_PAIR(pair, COND_3(__VA_ARGS__))
#define COND_5(pair, ...) COND_PAIR(pair, COND_4(__VA_ARGS__))
#define COND_6(pair, ...) COND_PAIR(pair, COND_5(__VA_ARGS__))
#define COND_7(pair, ...) COND_PAIR(pair, COND_6(__VA_ARGS__))
#define COND_8(pair, ...) COND_PAIR(pair, COND_7(__VA_ARGS__))
#define COUNT_ARGS(...) COUNT_ARGS_IMPL(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define COUNT_ARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define COND(...) CAT(COND_, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)
COND((b, IF(c,
d,
d)),
(f, IF(g,
h,
i)),
(1, j))
The expansion is still
((b) ? (((c) ? (d) : (d))) : (((f) ? (((g) ? (h) : (i))) : (((1) ? (j) : (0))))))
-- TXR Programming Language: http://nongnu.org/txrCygnal: Cygwin Native Application Library: http://kylheku.com/cygnalMastodon: @Kazinator@mstdn.ca