Warning: mysqli::__construct(): (HY000/1203): User howardkn already has more than 'max_user_connections' active connections in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\includes\artfuncs.php on line 21
Failed to connect to MySQL: (1203) User howardkn already has more than 'max_user_connections' active connections
Warning: mysqli::query(): Couldn't fetch mysqli in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\index.php on line 66
Article <20240405132341.870@kylheku.com>
Deutsch   English   Français   Italiano  
<20240405132341.870@kylheku.com>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!npeer.as286.net!npeer-ng0.as286.net!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Kaz Kylheku <643-408-1753@kylheku.com>
Newsgroups: comp.unix.shell,comp.unix.programmer,comp.lang.misc
Subject: Re: Command Languages Versus Programming Languages
Date: Fri, 5 Apr 2024 20:47:40 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 153
Message-ID: <20240405132341.870@kylheku.com>
References: <uu54la$3su5b$6@dont-email.me> <uu636l$7haj$1@dont-email.me>
 <20240329084454.0000090f@gmail.com> <uu6om5$cmv8$1@dont-email.me>
 <20240329101248.556@kylheku.com> <uu6t9h$dq4d$1@dont-email.me>
 <20240329104716.777@kylheku.com> <uu8p02$uebm$1@dont-email.me>
 <20240330112105.553@kylheku.com> <uudrfg$2cskm$1@dont-email.me>
 <87r0fp8lab.fsf@tudado.org> <uuehdj$2hshe$1@dont-email.me>
 <87wmpg7gpg.fsf@tudado.org> <LISP-20240402085115@ram.dialup.fu-berlin.de>
 <LISP-20240402091729@ram.dialup.fu-berlin.de>
 <wrap-20240402092558@ram.dialup.fu-berlin.de>
 <uui7hf$3gona$1@dont-email.me> <uuj1o5$3pvnq$1@dont-email.me>
 <87plv6jv1i.fsf@nosuchdomain.example.com>
 <wwv5xwyifq8.fsf@LkoBDZeT.terraraq.uk>
 <if-20240404121825@ram.dialup.fu-berlin.de> <uund4g$ugsb$1@dont-email.me>
 <uup8ul$1fr2t$1@dont-email.me>
Injection-Date: Fri, 05 Apr 2024 20:47:41 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="ceb148ea878d94e466846d7273339ae5";
	logging-data="1688663"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX19h5aNcfipgg/nNbG1iiZouV9NRNS7NQgA="
User-Agent: slrn/pre1.0.4-9 (Linux)
Cancel-Lock: sha1:Jbr6ZwqBJjJkL9PdaQTyMCAj1oM=
Bytes: 6437

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/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca