comp.lang.ada
 help / color / mirror / Atom feed
From: "Randy Brukardt" <randy@rrsoftware.com>
Subject: Re: Ada needs some modernization
Date: Tue, 31 May 2022 17:46:04 -0500	[thread overview]
Message-ID: <t765re$sj4$1@dont-email.me> (raw)
In-Reply-To: 75d90749-242f-42b8-ba0b-299f7ac693e0n@googlegroups.com

"Matt Borchers" <mattborchers@gmail.com> wrote in message 
news:75d90749-242f-42b8-ba0b-299f7ac693e0n@googlegroups.com...
>Throughout my career, I often find myself writing code similar to:
>
>if (A and B) or else (not A and C) then...
>
>and I always wished there was a better and clearer way to write this in 
>Ada.  Then along came if expressions.  >But, if expressions don't help that 
>much with readablity although it is arguably simpler:
>
>if (if A then B else C) then...
>
>What amendment can we suggest to the Ada syntax so the if expression be 
>better written when used in an if >statement?  I know other languages 
>support this and it often looks like  A ? B : C  or something similar. 
>That's >certainly not Ada-like IMO, but I can't think of something better.

Which is the rub. Ada is *not* about clever operators that hardly anyone 
knows what they do. Indeed, the original proposal for Ada 2012 was an 
"implies" operator. But we quickly found out that there are many people that 
don't know off-hand what function an implies operator does. We were pretty 
sure that every Ada programmer would understand an if expression.

Note that pretty much the only place that you should almost never use an if 
expression is in the choice of an if statement. If you already can write an 
if statement, you don't need an if expression! If expressions exist to make 
initializations and assertions like (Pre/Post) easier to write.

So I would never write your expression in the first place (either of them). 
I'd write something like:

    if A then
        if B then.
        else
       end if;
    else
        if C then
        else
       end if;
    end if;

The contents of the arms should be short anyway, and typically will just be 
a procedure call (and possibly some debugging, which is way easier if the 
conditions are kept simple).

>These same languages often also have a null check operator  A ?? B  (where 
>A and B are
>access types of the the same Type) such that if A is not null then A is 
>returned otherwise B
>is returned.  So useful and helpful!

Again, "utility" is not the criteria for Ada, rather understandability for 
future maintainers is the primary criteria. The last thing we need is a 
bunch of fancy but little used operators that some one cold when reading 
some unfamilar code. (Yes, of course you can look them up on-line, but 
stopping to doing so necessarily breaks your train of thought.)

And this construct fits nicely into an if expression, with no magic:

     (if A /= null then A else B)

and this extends nicely to more likely cases:
    (if A /= null then A elsif B /= null then B else raise Program_Error)

(Personally, I don't believe I've ever written something where such an 
operator would be useful; one needs to check everything for null (you can't 
usually can't assume B is nonnull, either). And the fall backs are generally 
more complex than using some other object. Moreover, probably A should have 
been declared null-excluding so it doesn't need to be tested in the first 
place. :-)

-----

> Again, I often find myself writing a loop to search for something and then 
> performing
> one or another action depending on the success of the search.  ...

....
>for i in arr'Range loop
>    if arr(i) = match then
>        --do something A
>       exit;
>    end if;
>then
>    --do something else B
>end loop;

>The "then" part only executes after the loop terminates normally, ...

In Ada terms, an exit *is* normal completion, so you would need some 
different terminology.

> i.e. only when the loop does NOT exit early by "exit" or "return" 
> statement.

We've discussed the "continue" statement multiple times, and have always 
ended up deciding that we are better off without it. (We've also discussed 
allowing "exit" from blocks, but that turns into a mess when blocks and 
loops get mixed, at least if one wants the code to do the same thing in Ada 
2012 and in future Ada.)

We'ver essentially decided that it is better to use a goto in such rare 
cases. The case you show above is similar.

  for i in arr'Range loop
      if arr(i) = match then
         --do something A
         goto Loop_Finished;
      end if;
  end loop;
  -- We get here if the search item is not found:
  --do something else B
 <<Loop_Finished>> null;

Remember that every feature added to a language adds costs in 
implementation, documentation, and in tools (analysis, checkers, etc.). A 
feature needs to be quite useful in order to make the cut.

Aside: in the case above, I've usually written such loops like:

  for i in arr'Range loop
      if arr(i) = match then
         --do something A
         exit;
      elsif i = arr'Last then
        --do something else B
        exit; -- Not really needed, but clearer what is going on.
      end if;
  end loop;

I've never been that happy with the duplication of the termination 
condition, but this avoids any extra objects or any gotos.

If I was going to try to fix your problem with a language feature, I'd 
probably try to define an attribute to avoid needing to duplicate the 
termination condition. Something like:

  Loop_Name: for i in arr'Range loop
      if arr(i) = match then
         --do something A
         exit Loop_Name;
      elsif i = Loop_Name'Range'Last then
        --do something else B
        exit Loop_Name; -- Not really needed, but clearer what is going on.
      end if;
  end loop Loop_Name;

(We probably would allow 'First and 'Last in such a case.) But this 
technique doesn't really work with user-defined iterators (which don't 
necessarily have a defined end), and I'm unsure if it is important enough 
for another whistle.

>I think syntax enhancements like these could go a long way to making Ada 
>feel like it is
>at least keeping up with modern languages and I think current programmers 
>expect
>"ease-of-use" syntax from today's languages.

Ada has *never* been about "ease-of-use". It is about readability, 
maintenability, and understandability. (See the "Design Goals" in the 
Introduction -- http://www.ada-auth.org/standards/2xrm/html/RM-0-2.html.)

Enhancing readability might also enhance ease of use (for instance, 
user-defined literals, target name symbols, and user-defined indexing all 
were added to enhance readability by avoiding duplicative text that provides 
little information), but it is never a primary goal for an Ada feature.

>Other contemporary modernized languages have taken ideas from Ada, but Ada 
>has not
>continued to pioneer ideas as quickly.  Perhaps that's by choice or design.

This is not true. Ada pioneers ideas all the time (see delta aggregates, 
aggregate iterators, the target symbol, parallel stuff, etc. from Ada 2022). 
What Ada does not do is waver from its core goal of readability and 
maintainability. So we don't waste time with tiny features that are more 
likely to harm readability and understandability than help. (Admittedly, 
what features are really necessary and which are just nice to have is always 
a personal choice.) Additionally, Ada has always been designed with a 
"building-block" approach, so we don't provide (say) a semaphore, but rather 
the tools (the protected type) to write one (and many other constructs). An 
if expression is a building block; funny boolean operators with limited uses 
are not.

I personally am not the least bit interested in worrying about ease-of-use 
gadgets in other languages. If programmers need such gadgets to be 
comfortable, they probably don't have the right mindset to be great Ada 
software engineers in the first place. Saving a few characters in a few 
expressions simply does not matter when compared to the effort needed to 
define and document a good data abstraction (for instance, an abstract data 
type and package).

There *are* features that probably would not interfere with Ada goals of 
readability. One of them that comes up periodically is an "at end" clause so 
one could write final wishes for a block/subprogram/package without writing 
a bunch of exception handlers (which doesn't work in the case of abort!) or 
one-time use controlled types. I'm sure there are others.

And certainly other languages have interesting features that Ada should 
steal, the Rust owned access types would be an obvious example. (Don't get 
me started on why Ada 2022 does not have those.) But "ease-of-use" is not 
interesting, at least when it does not make readability better. (I want 
people to replace "and" and "or" with if expressions as much as possible, as 
those are much more understandable. No more operators please!)

                                   Randy.

P.S. Man. did I spend a lot more time than I planned answering this. I hope 
it helps.



  parent reply	other threads:[~2022-05-31 22:46 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-31 17:54 Ada needs some modernization Matt Borchers
2022-05-31 19:05 ` Gautier write-only address
2022-05-31 19:55 ` Dmitry A. Kazakov
2022-05-31 22:46 ` Randy Brukardt [this message]
2022-06-01  7:24   ` John McCabe
2022-06-01 19:00 ` Jeffrey R.Carter
2022-06-02  5:56 ` G.B.
2022-06-10 16:38 ` Brad Moore
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox