comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Studying and Maintaining GNAT, Is There Any Interest in a New Group?
Date: Fri, 31 Aug 2018 10:48:25 +0200
Date: 2018-08-31T10:48:25+02:00	[thread overview]
Message-ID: <pmavco$u5d$1@gioia.aioe.org> (raw)
In-Reply-To: pm9uds$hpu$1@franka.jacob-sparre.dk

On 2018-08-31 01:25, Randy Brukardt wrote:

> They are primitive. That's what forces writing the traversal code into every
> operation. Consider the following node:
>      type Root_Node is abstract tagged null record;
>      type Expr_Tree_Access is access Root_Node'Class;
> 
>      procedure Fold (Expr : in out Root_Node); -- Fold the tree.
> 
>      type Binop is new Root_Node with record
>            Kind : Op;
>            Left, Right : Expr_Tree_Access;
>      end record;
> 
> and the implementation of the Folding operation:
>       overriding
>       procedure Fold (Expr : in out Binop);
> 
>       procedure Fold (Expr : in out Binop) is
>       begin
>             Fold (Expr.Left.all);
>             Fold (Expr.Right.all);
>             -- If Expr.Left and Expr.Right are constants, calculate the
> folded value.
>       end Fold;
> 
> This operation has to do recursive (dispatching calls) on the children. And
> so does every other such operation that gets defined (dozens).

Why isn't Fold class-wide:

    procedure Fold (Expr : in out Binop'Class) is
    begin
       Fold (Expr.Left.all);
       Fold (Expr.Right.all);
       Expr.Evaluate; -- This dispatches to the Op's implementation
    end Fold;

BTW, I prefer to fold constants before generating the tree. I.e. when 
Evaluate is called it returns either a value ("constant" node) or a new 
"dynamic" node.

>> As a general observation, anything you can do with subtypes of a single
>> type you can also do with a class of a types hierarchy. [There could be
>> some obstacles regarding indefinite vs definite types, but they usually
>> apply to both designs.]
> 
> This is true, you just have to write 3 times as much code to make the OO
> design work. And you lose the ability to do agile programming, because you
> have to implement so much new code to add a new node or operation (probably
> on the order of a week for either in an Ada compiler perspective -- dozens
> of operations and dozens of node types are needed there).

You would possibly save a comparable number of source lines in clients.

>>> Umm, we're talking about a compiler, and there never is a "final" version
>>> of a compiler.
>>
>> Final = deployed, of course.
> 
> Which is relevant how? It's just a snapshot of a continual evolution.

Each new release is another program. You might kill the whole package 
next time, the code is not stable. With OO I can have stable pieces of 
code frozen in separate packages which never change and keep adding 
volatile code without rewriting everything each time.

> ...
>>>> Note that inheritance would handle this safely. It will be:
>>>>
>>>>      Current.Token.Do_Something; -- A dispatching call override
>>>>
>>>> Do_Something would be abstract must-be-overridden for Float_Token.
>>>
>>> Sure, but that's what's maddening about using OOP in this way. You have
>>> to
>>> define and implement *every* such operation that way for a new node
>>> before
>>> anything can be done (even compiling the changed program).
>>
>> Exactly. This is called being typed. Operations do not exist without
>> types. The design with case-statements spread all over the client code is
>> untyped because chunks of client code under "whens" are not attributed to
>> any type, have no contract etc. OO allows us
>>
>> 1. To give a contract to this code
>> 2. To refactor and reuse this code
>> 3. To place it in separate compilation units *related* to the types
>> involved.
> 
> (1) There is no useful contracts for individual nodes -- all of the
> contracts with any meaning are on the tree as a whole. And it is the state
> of the nodes, rather than their kinds, which figure mainly into those
> contracts. (The state being part of the data, not part of the types.)

But when you fold constants you do that according to the types of the 
nodes. The question is if you try to map these types onto Ada types or not.

> (2) Refactoring isn't any harder with a variant design than it is with a OO
> design -- I do those sorts of things all of the time.

I find using free subprograms more difficult. They have no natural place 
to keep in. So I always forget which package holds this or that 
refactored subprogram and end up with several instances doing basically 
same thing.

> You would need so many getter/setter routines that you
> would be spending 50% of your time adding/fixing them rather than doing
> anything useful.

In my experience getter/setter tend to be stable. My problem is that 
they pollute package specification. This is one of the reasons why I'd 
like to have record interfaces:

    type Getters_Setters is interface record
       Field_1 : Integer; -- "Virtual" record field
       ...
    end record;
    type T is ... and Getters_Setters with ...

The type T need not to contain Field_1 physically. If it does not one 
should override getter and setter (in the private part).

> We've gotten a lot of mileage out of using aggregate
> assignments to ensure completeness rather than trying to make everything
> private.

It was wasting time, IMO. User-defined aggregates would be much simpler 
to add without burdening the language with dubious rules and 
counterintuitive constructs.

> Which does not answer the underlying question: how do you do agile
> development if adding an operation or new kind of node requires 4 days of
> coding?

I don't buy agile if that means generating false code. When I add an 
abstract operation I want the compiler to generate error messages the 
same way it does when a new case choice is added.

BTW, I feel uncomfortable about Ada 2005(?) change that a primitive 
function returning the type need not to be always overridden.

> For Ada at least, the only meaningful data structure is the expression tree.
> We don't care about the individual nodes outside of a handful of tree
> walking operations. Most everything talks specifically about the tree.

I'd like to have it reverse, hiding walking and exposing semantics of 
the nodes.

> In any case, I don't expect ever to agree with you on these points. I think
> a lot of people take strong typing too far -- but of course the sweet spot
> is hard to find. There may be an argument for going further than I do, but
> my experience doesn't show much value to that.

True, I want to push typing and static verification in general as far as 
possible. Nothing is too far to me. (:-))

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


  reply	other threads:[~2018-08-31  8:48 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-25 12:27 Studying and Maintaining GNAT, Is There Any Interest in a New Group? patrick
2018-08-25 13:56 ` Dan'l Miller
2018-08-25 16:00   ` patrick
2018-08-25 16:16 ` Luke A. Guest
2018-08-25 17:42   ` patrick
2018-08-25 19:25     ` Simon Wright
2018-08-25 20:24       ` patrick
2018-08-25 21:48         ` Luke A. Guest
2018-08-25 21:53           ` patrick
2018-08-25 22:05             ` Luke A. Guest
2018-08-26 19:54           ` Dan'l Miller
2018-08-26 20:14             ` Dan'l Miller
2018-08-26 22:52             ` Lucretia
2018-08-27  2:38               ` Dan'l Miller
2018-08-27 14:46                 ` Lucretia
2018-08-27 15:42                   ` Dan'l Miller
2018-08-27 21:27               ` Randy Brukardt
2018-08-28  7:26                 ` Dmitry A. Kazakov
2018-08-29  0:16                   ` Randy Brukardt
2018-08-29  8:20                     ` Dmitry A. Kazakov
2018-08-29 21:43                       ` Randy Brukardt
2018-08-30  7:55                         ` Dmitry A. Kazakov
2018-08-30 23:25                           ` Randy Brukardt
2018-08-31  8:48                             ` Dmitry A. Kazakov [this message]
2018-08-31 22:42                               ` Randy Brukardt
2018-09-02  8:02                                 ` Dmitry A. Kazakov
2018-09-04 22:18                                   ` Randy Brukardt
2018-08-29  3:02                 ` Paul Rubin
2018-08-29  6:18                   ` Luke A. Guest
2018-08-29 19:00                     ` Paul Rubin
2018-08-30  5:54                       ` Luke A. Guest
2018-08-30  6:29                         ` Paul Rubin
2018-08-27 21:18             ` Randy Brukardt
2018-08-27  9:37           ` Simon Wright
2018-08-27 16:54             ` Bill Findlay
2018-08-27 17:42               ` Shark8
2018-08-31 21:23                 ` Robert A Duff
2018-08-31 22:51                   ` Randy Brukardt
2018-09-01 19:42                     ` Robert A Duff
2018-09-02  8:04                       ` Dmitry A. Kazakov
2018-09-02 10:11                     ` AdaMagica
2018-09-02 12:10                       ` Jeffrey R. Carter
2018-09-02 14:30                         ` AdaMagica
2018-09-04 22:05                           ` Randy Brukardt
2018-09-01  7:41               ` Simon Wright
2018-09-01 17:27                 ` Bill Findlay
2018-08-27 17:35         ` Shark8
2018-08-25 21:17       ` Luke A. Guest
2018-08-25 23:16       ` Paul Rubin
2018-08-26  8:03         ` Rene
2018-08-26 10:09         ` Simon Wright
2018-08-25 16:43 ` Jeffrey R. Carter
2018-08-25 17:38   ` patrick
2018-08-25 17:39     ` Luke A. Guest
2018-08-25 17:45       ` patrick
replies disabled

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