• New aggregates with Ada 2022.

    From Blady@21:1/5 to All on Sun Jun 19 09:59:16 2022
    Hello,

    Following the example section of RM Ada 2022 § 4.3.5 Container
    Aggregate, I want to try map aggregates:

    453. type Map_Type is private
    454. with Aggregate => (Empty => Empty_Map,
    455. Add_Named => Add_To_Map);
    456.
    457. procedure Add_To_Map (M : in out Map_Type; Key : in Integer;
    Value : in String);
    458.
    459. Empty_Map : constant Map_Type;
    ... -- End of example code
    482. private
    ...
    488. type Map_Type is array (1..10) of String (1..10);
    489.
    490. procedure Add_To_Map (M : in out Map_Type; Key : in Integer;
    Value : in String) is null;
    491. Empty_Map : constant Map_Type := (1..10 => (1..10 => ' '));

    GNAT 12 reports:

    aarm_202x_ch04.adb:491:40: error: container aggregate must use [], not () aarm_202x_ch04.adb:491:42: error: choice must be static

    The first error seems to say that even Map_Type full view is known in
    the private part I can't use assignment with genuine array aggregates.
    It is a legal feature or GNAT is puzzled?
    Is there an other mean to assign array aggregates?

    I can't really figure out the meaning of the second error.
    Any idea?

    Thanks Pascal.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Wright@21:1/5 to Blady on Sun Jun 19 15:15:48 2022
    Blady <p.p11@orange.fr> writes:

    aarm_202x_ch04.adb:491:40: error: container aggregate must use [], not ()

    If you look at ARM202x 4.3.5, you'll see that *container* aggregates
    must use []. I'm sure there wa a whole lot of argument about this in the
    ARG!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blady@21:1/5 to All on Mon Jun 20 21:36:49 2022
    Le 19/06/2022 à 16:15, Simon Wright a écrit :
    Blady <p.p11@orange.fr> writes:

    aarm_202x_ch04.adb:491:40: error: container aggregate must use [], not ()

    If you look at ARM202x 4.3.5, you'll see that *container* aggregates
    must use []. I'm sure there wa a whole lot of argument about this in the
    ARG!

    Yes I was aware of that but I wanted to give Empty_Map its real value of
    the full type definition.

    My understanding is:
    you declare the aggregate aspect as:
    type Map_Type is private
    with Aggregate => (Empty => Empty_Map,
    Add_Named => Add_To_Map);
    thus:
    MM : Map_Type;
    ...
    MM := [] -- the compiler uses Empty_Map
    MM := [1=>"toto", 4=>"titi"]; -- the compiler uses Add_To_Map

    now if I declare:
    Empty_Map : constant Map_Type := [];
    then it could be an recursive infinite call, could be?

    Note : in this latter case the compiler issues a ICE: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106031

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Wright@21:1/5 to Blady on Mon Jun 20 23:01:41 2022
    Blady <p.p11@orange.fr> writes:

    Le 19/06/2022 à 16:15, Simon Wright a écrit :
    Blady <p.p11@orange.fr> writes:

    aarm_202x_ch04.adb:491:40: error: container aggregate must use [], not () >> If you look at ARM202x 4.3.5, you'll see that *container* aggregates
    must use []. I'm sure there wa a whole lot of argument about this in the
    ARG!

    Yes I was aware of that but I wanted to give Empty_Map its real value
    of the full type definition.

    My understanding is:
    you declare the aggregate aspect as:
    type Map_Type is private
    with Aggregate => (Empty => Empty_Map,
    Add_Named => Add_To_Map);
    thus:
    MM : Map_Type;
    ...
    MM := [] -- the compiler uses Empty_Map
    MM := [1=>"toto", 4=>"titi"]; -- the compiler uses Add_To_Map

    now if I declare:
    Empty_Map : constant Map_Type := [];
    then it could be an recursive infinite call, could be?

    I think you'd need to supply the contents - Empty_Map here is presumably
    the full declaration (it is in your PR). Fixing this, the compiler is
    still confused (it thinks that 'others' in [others => [others => ' ']]
    isn't static - also if replaced by '1 .. 10'!!!).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Blady on Mon Jun 20 16:47:32 2022
    "Blady" <p.p11@orange.fr> wrote in message
    news:t8ml0l$1vo2$1@gioia.aioe.org...
    Hello,

    Following the example section of RM Ada 2022 § 4.3.5 Container Aggregate,
    I want to try map aggregates:

    453. type Map_Type is private
    454. with Aggregate => (Empty => Empty_Map,
    455. Add_Named => Add_To_Map);
    456.
    457. procedure Add_To_Map (M : in out Map_Type; Key : in Integer;
    Value : in String);
    458.
    459. Empty_Map : constant Map_Type;
    ... -- End of example code
    482. private
    ...
    488. type Map_Type is array (1..10) of String (1..10);

    This type is illegal, by 4.3.5(10/5):

    If the container type of an Aggregate aspect is a private type, the full
    type of the container type shall not be an array type.

    The reason for this is obvious in your question: it is ambiguous if an aggregate is an array aggregate or a container aggregate wherever the full
    type is visible, and that is not worth making work (any choice would be a surprise in some contexts).

    Apparently, GNAT failed to check for this error (probably because there
    aren't ACATS tests yet for Ada 2022, so errors of omission are very hard to find, not having a vetted set of tests).

    Secondly, early post Ada 2022 AIs have removed the possibility of using a constant for Empty_Map, since it does nto work with inheritance (and
    container aggregates are supposed to work with inheritance). So while GNAT
    may allow you to define Empty_Map this way now, it won't for very long. It
    will need to be a function.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jesper Quorning@21:1/5 to All on Mon Jun 20 15:10:49 2022
    It look like the Aggregate aspect has some rough edges.
    This code leads to internal compiler error with gnatmake 12.1.0:

    package Container_Aggregates is
    type Array_Type is
    array (1 .. 10) of Integer
    with Aggregate => (Empty => Empty_Array);

    Empty_Array : constant Array_Type := [1..10 => 123];
    end Container_Aggregates;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Tue Jun 21 00:18:01 2022
    On 2022-06-20 23:47, Randy Brukardt wrote:

    The reason for this is obvious in your question: it is ambiguous if an aggregate is an array aggregate or a container aggregate wherever the full type is visible, and that is not worth making work (any choice would be a surprise in some contexts).

    I don't agree that making the language regular does not worth work. The
    choice is obviously inconsistent with handling both existing cases:

    1. Built-in operations -> hiding:

    type T is private;
    function "+" (Left, Right : T) return T; -- Perfectly legal
    private
    type T is range 1..100;

    2. Primitive operations -> overriding.

    What's good for the goose is good for the gander? Nope. Here is a
    totally new way of handling an operation!

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jesper Quorning@21:1/5 to All on Mon Jun 20 15:59:51 2022
    tirsdag den 21. juni 2022 kl. 00.10.52 UTC+2 skrev Jesper Quorning:
    This code leads to internal compiler error with gnatmake 12.1.0:

    This is the bug report:
    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106037
    The crash happens another place than the #106031 report by Blady.

    I ran into a third ICE with erroneous memory access while playing around with an access type.


    /Jesper

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Tue Jun 21 18:28:17 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t8qrmo$p79$1@gioia.aioe.org...
    On 2022-06-20 23:47, Randy Brukardt wrote:

    The reason for this is obvious in your question: it is ambiguous if an
    aggregate is an array aggregate or a container aggregate wherever the
    full
    type is visible, and that is not worth making work (any choice would be a
    surprise in some contexts).

    I don't agree that making the language regular does not worth work.

    There's always a way, but is it worth the implementation effort? And would
    it be confusing to use?

    The choice is obviously inconsistent with handling both existing cases:

    1. Built-in operations -> hiding:

    type T is private;
    function "+" (Left, Right : T) return T; -- Perfectly legal
    private
    type T is range 1..100;

    This case is not worth the effort, IMHO. (Of course, it is in the language
    now, so we're stuck with it.) If I was running the circus, private types
    could only be completed with a record type. 99% of the time, that's what you want. And the other 1% of the time, you will eventually end up changing it
    into a record for one reason or the other. So why pollute the language rules for something primarily useful in ACATS tests?

    2. Primitive operations -> overriding.

    What's good for the goose is good for the gander? Nope. Here is a totally
    new way of handling an operation!

    The problem here is illustrated by the OP, who seemed to expect to get the container aggregate when the full view is visible. We looked at making the container aggregate invisible and allowing the array aggregate in the full view, but it would be something new (the contents of aggregates don't depend
    on visibility in Ada 2012), and it seems useless (see my answer to [1]).

    That is, the OPs construct is primarily useful in small examples; it's not a real world thing you would want to do. (There ALWAYS is some other data that you need to go along with an array: a length, a validity flag, etc.) So why make implementers spend a lot of effort implementing it??

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to All on Tue Jun 21 18:20:10 2022
    Thia ia also illegal: the aspect aggregate is defined "for a type other than
    an array type", so the aspect should not even be recognized in this context.

    Randy.

    "Jesper Quorning" <jesper.quorning@gmail.com> wrote in message news:9e3aa56d-42b3-4552-8027-908403118721n@googlegroups.com...
    tirsdag den 21. juni 2022 kl. 00.10.52 UTC+2 skrev Jesper Quorning:
    This code leads to internal compiler error with gnatmake 12.1.0:

    This is the bug report:
    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106037
    The crash happens another place than the #106031 report by Blady.

    I ran into a third ICE with erroneous memory access while playing around
    with an access type.


    /Jesper

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Tue Jun 21 18:39:43 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t8qrmo$p79$1@gioia.aioe.org...
    ...
    1. Built-in operations -> hiding:

    type T is private;
    function "+" (Left, Right : T) return T; -- Perfectly legal
    private
    type T is range 1..100;

    2. Primitive operations -> overriding.

    BTW, these two are really the same thing. In the first example, the "+" is overriding the predefined operation.

    But note an important difference here from the aggregate case: in no case is
    an operation available for the private type that is *not* available for the full view. Since the syntax and semantics of container aggregates and array aggregate are subtly different (they are as close as we could make them, but that is not that close), there definitely are things that would be only possible when written for the private view. That would be new for Ada. So
    while a definition could be made, it would be confusing in some cases. And
    this case isn't useful enough to make that effort.

    BTW2, there are many things in Ada that would be possible with effort but
    are illegal for one reason or another. Part of the reason for doing that is that it is always possible to allow such things in the future -- that would
    be a compatible change. OTOH, defining them sloppily would leave us stuck forever with an expensive and relatively useless feature. For instance, the rather strict limitations on the use and contents of a declare expression
    fall into that category. Allowing more would be possible, but it would have far-reaching effects on compilers and on the language definition. Not worth
    the cost at this point, perhaps that will change.

    Randy.
    .

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Wed Jun 22 11:04:09 2022
    On 2022-06-22 01:28, Randy Brukardt wrote:

    This case is not worth the effort, IMHO. (Of course, it is in the language now, so we're stuck with it.) If I was running the circus, private types could only be completed with a record type.

    Just like aggregates now, record types *must* have interface. Your
    "circus" will inevitable face this same problem again - how to define
    record members of a private type implemented by a built-in record type
    in the full view? The language must universally handle all sorts of
    interfaces.

    The problem here is illustrated by the OP, who seemed to expect to get the container aggregate when the full view is visible. We looked at making the container aggregate invisible and allowing the array aggregate in the full view, but it would be something new (the contents of aggregates don't depend on visibility in Ada 2012), and it seems useless (see my answer to [1]).

    I would first answer basic questions, which interfaces have array vs user-defined aggregate/index. How are they related to each other etc.

    That is, the OPs construct is primarily useful in small examples; it's not a real world thing you would want to do. (There ALWAYS is some other data that you need to go along with an array: a length, a validity flag, etc.) So why make implementers spend a lot of effort implementing it??

    Well, I can give a useful example straight away. A string has two array interfaces, the encoding and the character view. The former must be a
    built-in array.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Wed Jun 22 10:26:34 2022
    On 2022-06-22 01:39, Randy Brukardt wrote:
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t8qrmo$p79$1@gioia.aioe.org...
    ...
    1. Built-in operations -> hiding:

    type T is private;
    function "+" (Left, Right : T) return T; -- Perfectly legal
    private
    type T is range 1..100;

    2. Primitive operations -> overriding.

    BTW, these two are really the same thing. In the first example, the "+" is overriding the predefined operation.

    Yes, they should be in a better world. A primitive operation is always reachable. The case above works differently from:

    type T is private;
    overriding
    function "+" (Left, Right : T) return T is abstract;

    But this is a deeper problem of having such operations primitive.

    But note an important difference here from the aggregate case: in no case is an operation available for the private type that is *not* available for the full view. Since the syntax and semantics of container aggregates and array aggregate are subtly different (they are as close as we could make them, but that is not that close), there definitely are things that would be only possible when written for the private view. That would be new for Ada. So while a definition could be made, it would be confusing in some cases. And this case isn't useful enough to make that effort.

    Much could be resolved by attributing proper types to all assumed or
    real intermediate steps:

    type T is private;
    function "+" (Left, Right : T) return T;
    private
    type T_Parent is range 1..100;
    type T is new T_Parent;

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Wed Jun 22 20:06:53 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t8ulu9$jca$1@gioia.aioe.org...
    On 2022-06-22 01:28, Randy Brukardt wrote:
    ...
    Well, I can give a useful example straight away. A string has two array interfaces, the encoding and the character view. The former must be a built-in array.

    The interface for a string should be quite different from that for an array, they're not related at all. One might implement a string with a record type that has an array component, but never as a bare array. (That leads to nonsense, which Ada sadly has proven clearly.

    Indeed, if you consider everything to have an interface, arrays themselves cease to be a fundemental part of a language design and just become another interface. (How something gets implemented should not be part of a language design, so long as the design does not prevent an efficient implementation.)
    I certainly would not treat them as special in any way, just a series of function calls. (Possibly records could be treated that way as well,
    although it is less clear that an efficient implementation is possible for them.)

    Randy.


    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Wed Jun 22 20:10:06 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t8ujnr$1hvf$1@gioia.aioe.org...
    On 2022-06-22 01:39, Randy Brukardt wrote:
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
    news:t8qrmo$p79$1@gioia.aioe.org...
    ...
    1. Built-in operations -> hiding:

    type T is private;
    function "+" (Left, Right : T) return T; -- Perfectly legal
    private
    type T is range 1..100;

    2. Primitive operations -> overriding.

    BTW, these two are really the same thing. In the first example, the "+"
    is
    overriding the predefined operation.

    Yes, they should be in a better world. A primitive operation is always reachable. The case above works differently from:

    type T is private;
    overriding
    function "+" (Left, Right : T) return T is abstract;

    But this is a deeper problem of having such operations primitive.

    But note an important difference here from the aggregate case: in no case
    is
    an operation available for the private type that is *not* available for
    the
    full view. Since the syntax and semantics of container aggregates and
    array
    aggregate are subtly different (they are as close as we could make them,
    but
    that is not that close), there definitely are things that would be only
    possible when written for the private view. That would be new for Ada. So
    while a definition could be made, it would be confusing in some cases.
    And
    this case isn't useful enough to make that effort.

    Much could be resolved by attributing proper types to all assumed or real intermediate steps:

    type T is private;
    function "+" (Left, Right : T) return T;
    private
    type T_Parent is range 1..100;
    type T is new T_Parent;

    Don't think this changes anything (at least not in Ada as it stands), since that is essentially the meaning of "range 1 .. 100":

    type Some_Int is range 1 .. 100;

    means

    type Some_Int is new <Some_Int_Chosen_by_the_Impl> range 1 .. 100;

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Thu Jun 23 11:32:44 2022
    On 2022-06-23 03:10, Randy Brukardt wrote:

    Don't think this changes anything (at least not in Ada as it stands), since that is essentially the meaning of "range 1 .. 100":

    type Some_Int is range 1 .. 100;

    means

    type Some_Int is new <Some_Int_Chosen_by_the_Impl> range 1 .. 100;

    I mean that then we would have two distinct types to assign conflicting operations to. So "+" each goes to a separate type.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From G.B.@21:1/5 to Dmitry A. Kazakov on Thu Jun 23 12:53:12 2022
    On 23.06.22 11:32, Dmitry A. Kazakov wrote:

    In any case having an explicit array interface does not preclude built-in arrays.

    Indeed, if there were no built-in arrays, how would one

    - specify aspects like "contiguous memory",
    - permit implementations to create efficient addressing
    for arrays' storage units
    - map to hardware?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Thu Jun 23 20:24:32 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t91buq$10im$1@gioia.aioe.org...
    On 2022-06-23 03:06, Randy Brukardt wrote:
    ...
    (How something gets implemented should not be part of a language
    design, so long as the design does not prevent an efficient
    implementation.)
    I certainly would not treat them as special in any way, just a series of
    function calls. (Possibly records could be treated that way as well,
    although it is less clear that an efficient implementation is possible
    for
    them.)

    Syntax sugar for subprogram calls is not enough because it does not allow generic programming. One should be able to write a program that deals with any instance of the interface. Like a generic body working with any actual array or a class-wide body which unfortunately is impossible to have for arrays presently.

    You're thinking too small. Obviously, in a language without an syntactic
    array construct, every data structure would be some sort of record. So class-wide operations would be available for all of those -- and without all
    of the complications of a separate formal array type. The idea is to have
    one mechanism for pretty much everything, and let the compiler sort out the results. Back when we created Janus/Ada, that wasn't really practical
    because of memory and CPU speed constraints, but none of that holds true anymore. Simplify the language, complicate the compiler!

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to G.B. on Thu Jun 23 20:21:09 2022
    "G.B." <bauhaus@notmyhomepage.invalid> wrote in message news:t91gmo$rh1$1@dont-email.me...
    On 23.06.22 11:32, Dmitry A. Kazakov wrote:

    In any case having an explicit array interface does not preclude built-in
    arrays.

    Indeed, if there were no built-in arrays, how would one

    - specify aspects like "contiguous memory",
    - permit implementations to create efficient addressing
    for arrays' storage units
    - map to hardware?

    With aspects, of course, that are part of the "interface". Why do you think that one needs a visible built-in array in order to support these (or any other) operations?

    Again, at the implementation level, surely there is some sort of built-in array. But one does not need to expose that at the programmer level.
    "Efficient addressing" is the compiler's job, it will do whatever makes
    sense for the target (and those vary quite a bit).

    For example, "contiguous" is an aspect that Ada is missing (but should
    have). Implementations should have the freedom to pick any implementation in the absence of such as aspect (which should be rarely needed, mainly for interfacing with hardware and foreign software).

    Mapping to hardware could be handled with a "fixed vector" container (one
    that would be rarely used other than for interfacing). It doesn't require an array, just something with the right semantics.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Fri Jun 24 08:50:14 2022
    On 2022-06-24 03:24, Randy Brukardt wrote:
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t91buq$10im$1@gioia.aioe.org...
    On 2022-06-23 03:06, Randy Brukardt wrote:
    ...
    (How something gets implemented should not be part of a language
    design, so long as the design does not prevent an efficient
    implementation.)
    I certainly would not treat them as special in any way, just a series of >>> function calls. (Possibly records could be treated that way as well,
    although it is less clear that an efficient implementation is possible
    for
    them.)

    Syntax sugar for subprogram calls is not enough because it does not allow
    generic programming. One should be able to write a program that deals with >> any instance of the interface. Like a generic body working with any actual >> array or a class-wide body which unfortunately is impossible to have for
    arrays presently.

    You're thinking too small. Obviously, in a language without an syntactic array construct, every data structure would be some sort of record.

    They are fundamentally different. Record interface is static mapping:

    identifier -> value

    1D array interface is dynamic mapping:

    ordered value -> value

    It not only has run-time semantics of (indexing). It is also ordering of
    the index which implies enumeration, ranges, slices.

    So
    class-wide operations would be available for all of those -- and without all of the complications of a separate formal array type. The idea is to have
    one mechanism for pretty much everything, and let the compiler sort out the results. Back when we created Janus/Ada, that wasn't really practical
    because of memory and CPU speed constraints, but none of that holds true anymore. Simplify the language, complicate the compiler!

    I don't buy the idea of run-time penalty for having abstract data types
    and I don't see why built-in arrays cannot coexist with user-defined
    ones without turning the language into LISP. Furthermore, the age of
    free CPU cycles came to an end. Soon we will have return back to sanity.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Fri Jun 24 22:13:44 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t93mr6$pvm$1@gioia.aioe.org...
    On 2022-06-24 03:24, Randy Brukardt wrote:
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
    news:t91buq$10im$1@gioia.aioe.org...
    On 2022-06-23 03:06, Randy Brukardt wrote:
    ...
    (How something gets implemented should not be part of a language
    design, so long as the design does not prevent an efficient
    implementation.)
    I certainly would not treat them as special in any way, just a series
    of
    function calls. (Possibly records could be treated that way as well,
    although it is less clear that an efficient implementation is possible >>>> for
    them.)

    Syntax sugar for subprogram calls is not enough because it does not
    allow
    generic programming. One should be able to write a program that deals
    with
    any instance of the interface. Like a generic body working with any
    actual
    array or a class-wide body which unfortunately is impossible to have for >>> arrays presently.

    You're thinking too small. Obviously, in a language without an syntactic
    array construct, every data structure would be some sort of record.

    They are fundamentally different. Record interface is static mapping:

    identifier -> value

    1D array interface is dynamic mapping:

    ordered value -> value

    It not only has run-time semantics of (indexing). It is also ordering of
    the index which implies enumeration, ranges, slices.

    Dymanic means a function. And there is no reason to treat a few functions as special (again, at the user level).

    Something purely-compile time (like the selection of record components)
    clearly needs some special semantics. Not so clear with dynamic things.

    So
    class-wide operations would be available for all of those -- and without
    all
    of the complications of a separate formal array type. The idea is to have
    one mechanism for pretty much everything, and let the compiler sort out
    the
    results. Back when we created Janus/Ada, that wasn't really practical
    because of memory and CPU speed constraints, but none of that holds true
    anymore. Simplify the language, complicate the compiler!

    I don't buy the idea of run-time penalty for having abstract data types
    and I don't see why built-in arrays cannot coexist with user-defined ones without turning the language into LISP.

    They add a huge amount of complication for very little gain. One could
    simplify them (getting rid of mistaken features like slices), but you still would want a user-defined version. And once you have that, you no longer
    need a special version - you just have some predefined versions (just like
    Ada handles operators).

    Furthermore, the age of free CPU cycles came to an end. Soon we will have return back to sanity.

    I don't think programming abstractly and translating that into good code
    will ever be a bad idea. After all, that is the idea behind Ada. If you
    truly want to worry about the cost of compilation, then you have program in
    a very close to the metal language, even lower level than C. And current machines are way harder to generate code for than the Z-80 that we started
    out on (and even then, we generated pretty bad code with the very tiny compiler).

    I'd rather plan for a future where the compiler tool set does a lot of correctness checking for one's programs; code generation will always be much cheaper than that (especially if you do not need bleeding edge performance). Simplify (and abstract) the language, complicate the compiler!

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Sat Jun 25 10:50:54 2022
    On 2022-06-25 05:13, Randy Brukardt wrote:
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t93mr6$pvm$1@gioia.aioe.org...
    On 2022-06-24 03:24, Randy Brukardt wrote:

    You're thinking too small. Obviously, in a language without an syntactic >>> array construct, every data structure would be some sort of record.

    They are fundamentally different. Record interface is static mapping:

    identifier -> value

    1D array interface is dynamic mapping:

    ordered value -> value

    It not only has run-time semantics of (indexing). It is also ordering of
    the index which implies enumeration, ranges, slices.

    Dymanic means a function. And there is no reason to treat a few functions as special (again, at the user level).

    No. Identifier is not a value, it is a static name. This allows us to
    have any statically chosen type on the right side of the mapping.

    With a dynamic mapping we must have the same type for all outcomes, e.g.
    of the array element.

    I don't buy the idea of run-time penalty for having abstract data types
    and I don't see why built-in arrays cannot coexist with user-defined ones
    without turning the language into LISP.

    They add a huge amount of complication for very little gain.

    We have different priorities here. I see arrays with slices as one of
    the most important language features. Especially considering formal verification and validation.

    Furthermore, the age of free CPU cycles came to an end. Soon we will have >> return back to sanity.

    I don't think programming abstractly and translating that into good code
    will ever be a bad idea. After all, that is the idea behind Ada. If you
    truly want to worry about the cost of compilation, then you have program in
    a very close to the metal language, even lower level than C. And current machines are way harder to generate code for than the Z-80 that we started out on (and even then, we generated pretty bad code with the very tiny compiler).

    No, I worry about cost of execution. You want to simplify the compiler
    at the expense of the program complexity and efficiency of its code.

    I'd rather plan for a future where the compiler tool set does a lot of correctness checking for one's programs;

    Yes and correctness checking requires proper and very refined
    abstractions you are ready to throw away. Here is a contradiction. In a language like Forth there is basically nothing to check.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Mon Jun 27 16:37:08 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t96i9f$1mc1$1@gioia.aioe.org...
    On 2022-06-25 05:13, Randy Brukardt wrote:
    ...
    I don't think programming abstractly and translating that into good code
    will ever be a bad idea. After all, that is the idea behind Ada. If you
    truly want to worry about the cost of compilation, then you have program
    in
    a very close to the metal language, even lower level than C. And current
    machines are way harder to generate code for than the Z-80 that we
    started
    out on (and even then, we generated pretty bad code with the very tiny
    compiler).

    No, I worry about cost of execution. You want to simplify the compiler at
    the expense of the program complexity and efficiency of its code.

    I think we strongly agree here. I want to simplify the front-end to
    strengthen abstractions, and so that the effort can be put where it belongs,
    on static analysis/optimization and on code generation. These things are
    mostly fancy pattern matching, and the more of it that you can do, the
    better. Time spent implementing features that don't increase the expressive power (or worse, compilicate code generation in all cases) is counter-productive.

    I'd rather plan for a future where the compiler tool set does a lot of
    correctness checking for one's programs;

    Yes and correctness checking requires proper and very refined abstractions you are ready to throw away. Here is a contradiction. In a language like Forth there is basically nothing to check.

    Slices are not an abstraction. They are a way to describe a particular kind
    of processor operation in a vaguely abstract way. But they don't extend to user-defined structures or even multi-dimensional maps (arrays if you
    prefer) in any practical way. The distributed overhead that they cause is immense (for instance, you can't have a discontigious array represesentation with slices, unless you are willing to pay a substantial cost for *every*
    array parameter). They're the anti-abstraction feature.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Niklas Holsti@21:1/5 to Randy Brukardt on Tue Jun 28 08:36:21 2022
    On 2022-06-28 0:37, Randy Brukardt wrote:

    Slices are not an abstraction. They are a way to describe a particular kind of processor operation in a vaguely abstract way.


    The abstraction is the concept of a one-dimensional array (a vector or a sequence). Slicing such an object -- taking a subsequence -- seems a
    very natural operation to me, even on the abstraction level.


    The distributed overhead that they [slices] cause is immense (for
    instance, you can't have a discontigious array represesentation with
    slices,


    Why would you want to have a non-contiguous representation for
    one-dimensional arrays? Perhaps to make "unbounded" (extensible) arrays?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Tue Jun 28 09:52:11 2022
    On 2022-06-27 23:37, Randy Brukardt wrote:

    The distributed overhead that they cause is
    immense (for instance, you can't have a discontigious array represesentation with slices, unless you are willing to pay a substantial cost for *every* array parameter). They're the anti-abstraction feature.

    There is nothing wrong with having non-contiguous slices of
    non-contiguous arrays! Contiguity of index does not automatically imply contiguity of element allocation, unless specifically required by the
    [sub]type constraint.

    1D array abstraction is a mapping index -> element where

    1. Index has an order. Index has operations 'Succ and 'Pred;

    2. The mapping is convex. If there are elements for two indices, then
    there are elements for all indices between them.

    Contiguity is a representation constraint.

    One should be able to have an array equivalent of unbounded string with unbounded slices both allocated non-contiguously. The slices you could
    shrink or expand:

    Text (45..80) := ""; -- Cut a piece off

    At the same time one should have a contiguous subtype of the same
    unbounded string for interfacing purposes, dealt by copy-out copy-in.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Niklas Holsti on Tue Jun 28 23:01:36 2022
    "Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message news:jhviamFe72sU1@mid.individual.net...
    On 2022-06-28 0:37, Randy Brukardt wrote:

    Slices are not an abstraction. They are a way to describe a particular
    kind
    of processor operation in a vaguely abstract way.

    The abstraction is the concept of a one-dimensional array (a vector or a >sequence).

    But there is (or shouldn't be) anything special about a one-dimensional
    array (presuming you intend to allow arrays with more dimensions). And the "abstraction" you talk about is selecting a bunch of barely related elements from a multi-dimensional array.

    ...
    Why would you want to have a non-contiguous representation for one-dimensional arrays? Perhaps to make "unbounded" (extensible) arrays?

    Exactly. If you don't know how large something will grow to, it's better to allocate it in pieces than to copy it each time it grows.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Tue Jun 28 23:07:01 2022
    What you say here is precisely how they should work. But you would make the cost of supporting that necessary on every array object, because one could
    not know when an array is passed as a parameter what sort of representation
    it has. So one has to use dispatching helper operations to implement all assignments. And that's way more expensive than traditional array implementation.

    If you didn't have slices that could be passed as array parameters, then
    that problem does not exist. And I don't think slices are sufficiently worthwhile to force expensive, unoptimizable code.

    Randy.

    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t9ebvc$1amt$1@gioia.aioe.org...
    On 2022-06-27 23:37, Randy Brukardt wrote:

    The distributed overhead that they cause is
    immense (for instance, you can't have a discontigious array
    represesentation
    with slices, unless you are willing to pay a substantial cost for *every*
    array parameter). They're the anti-abstraction feature.

    There is nothing wrong with having non-contiguous slices of non-contiguous arrays! Contiguity of index does not automatically imply contiguity of element allocation, unless specifically required by the [sub]type
    constraint.

    1D array abstraction is a mapping index -> element where

    1. Index has an order. Index has operations 'Succ and 'Pred;

    2. The mapping is convex. If there are elements for two indices, then
    there are elements for all indices between them.

    Contiguity is a representation constraint.

    One should be able to have an array equivalent of unbounded string with unbounded slices both allocated non-contiguously. The slices you could
    shrink or expand:

    Text (45..80) := ""; -- Cut a piece off

    At the same time one should have a contiguous subtype of the same
    unbounded string for interfacing purposes, dealt by copy-out copy-in.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Wed Jun 29 09:24:36 2022
    On 2022-06-29 06:07, Randy Brukardt wrote:
    What you say here is precisely how they should work. But you would make the cost of supporting that necessary on every array object, because one could not know when an array is passed as a parameter what sort of representation it has. So one has to use dispatching helper operations to implement all assignments. And that's way more expensive than traditional array implementation.

    It is already there because Ada 83 arrays have definite and indefinite representations. Adding a user-defined representation on top is nothing.

    If you didn't have slices that could be passed as array parameters, then
    that problem does not exist. And I don't think slices are sufficiently worthwhile to force expensive, unoptimizable code.

    You still must be able to pass a definite array for indefinite argument
    and conversely. Slices change nothing.

    The language must expose subtype conversions per adding removing
    constraints to the user. This is what definite/indefinite and slicing
    does. But also, it is what the type tag could be for class-wide arrays
    or scalar types. I am talking about Integer'Class. And it is what
    measurement units constraints are.

    There should be a universal mechanism of dealing with type constraints
    unifying discriminants/tags/bounds.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Jeffrey R.Carter on Wed Jun 29 11:04:09 2022
    On 2022-06-29 10:30, Jeffrey R.Carter wrote:

    * Maps are usually constrained. It does not make sense to concatenate,
    sort, slice, or slide a map. The abstraction of a map includes
    non-discrete key subtypes, so arrays used as maps are a special case.

    There is an important distinction regarding the keys. Some maps assume
    keys ordered or have a distance measure, so that the map would have
    operations like next-to-this or closest-neighbor-of. Another type of
    maps is when keys are totally unordered, e.g. relational tables (key =
    tuple).

    A language that provided direct support for these abstractions should
    not need to provide arrays.

    Which is of course impossible considering the variety of maps (e.g.
    graph is a map etc) and all problem-space specific.

    Array as a building block is the best way to go, IMO.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Randy Brukardt on Wed Jun 29 10:30:20 2022
    On 2022-06-29 06:01, Randy Brukardt wrote:

    But there is (or shouldn't be) anything special about a one-dimensional
    array (presuming you intend to allow arrays with more dimensions). And the "abstraction" you talk about is selecting a bunch of barely related elements from a multi-dimensional array.

    Arrays are usually used to implement map, (mathematical) matrices and vectors, or sequences. Each usage tends to have unique features:

    * Maps are usually constrained. It does not make sense to concatenate, sort, slice, or slide a map. The abstraction of a map includes non-discrete key subtypes, so arrays used as maps are a special case.

    * Matrices have component types that behave like numbers. The mathematical definition of matrices includes integer indices with a lower bound of 1. Vectors
    are usually considered to be matrices of one column ("column vector") which can be transposed to obtain matrices of one row ("row vector").

    * Sequences are usually unconstrained. Typical discussion of sequences outside of programming use integer values to indicate positions, using terms such as the
    first thing in a sequence, the second thing, ..., so indices should be of an integer type with a lower bound of 1. It sometimes makes sense to concatenate, sort, slice, or slide sequences.

    A language that provided direct support for these abstractions should not need to provide arrays.

    --
    Jeff Carter
    "[T]he language [Ada] incorporates many excellent structural
    features which have proved their value in many precursor
    languages ..."
    C. A. R. Hoare
    180

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Niklas Holsti@21:1/5 to Jeffrey R.Carter on Wed Jun 29 14:06:31 2022
    On 2022-06-29 11:30, Jeffrey R.Carter wrote:
    On 2022-06-29 06:01, Randy Brukardt wrote:

    But there is (or shouldn't be) anything special about a
    one-dimensional array (presuming you intend to allow arrays with
    more dimensions). And the "abstraction" you talk about is selecting
    a bunch of barely related elements from a multi-dimensional array.

    Arrays are usually used to implement map, (mathematical) matrices and vectors, or sequences. Each usage tends to have unique features:

    * Maps are usually constrained. It does not make sense to concatenate,
    sort, slice, or slide a map.

    In mathematics, maps (functions) are often sliced, in other words
    restricted to a subset of their full domain. They are also often
    concatenated, in the sense of combining functions defined on separate
    domain sets into a combined function defined on the union of those
    separate domain sets. Those operations would be useful in programs too.

    The essential aspect of maps and map operations is that there is no
    "sliding" that changes the relationship of domain values (keys) with
    range values.

    That said, it very often makes sense to provide sorted access to the
    elements of a map, sorted by some criterion, while maintaining the
    relationship of keys and their mapped values. That might be seen as
    sorting the map into a sequence (as described below).


    * Matrices have component types that behave like numbers. The
    mathematical definition of matrices includes integer indices with a
    lower bound of 1. Vectors are usually considered to be matrices of one
    column ("column vector") which can be transposed to obtain matrices of
    one row ("row vector").


    Computations that really use matrices (as opposed to multi-dimensional
    maps or plain arrays) very often make use of slices in the form of
    selected rows, columns, diagonals, or contiguous submatrices, with
    sliding of indices.


    * Sequences are usually unconstrained. Typical discussion of sequences outside of programming use integer values to indicate positions, using
    terms such as the first thing in a sequence, the second thing, ..., so indices should be of an integer type with a lower bound of 1. It
    sometimes makes sense to concatenate, sort, slice, or slide sequences.


    Yes. But IME it is almost never useful /not/ to slide the indices.


    A language that provided direct support for these abstractions should
    not need to provide arrays.


    Except if someone invents new abstractions and needs a "raw memory" type
    to implement them.

    I like that Ada is a multi-level language, with both high-level services
    (eg. containers) and low-level services (arrays). As long as Ada uses
    arrays to represent sequences, such as character strings, array slices
    are quite nice to have, at least as values. I have not often needed to
    use a slice as a variable (eg. as the target of an assignment, or as an
    "out" parameter).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Niklas Holsti on Wed Jun 29 14:53:33 2022
    On 2022-06-29 13:06, Niklas Holsti wrote:
    On 2022-06-29 11:30, Jeffrey R.Carter wrote:

    * Maps are usually constrained. It does not make sense to concatenate, sort, >> slice, or slide a map.

    In mathematics, maps (functions) are often sliced, in other words restricted to
    a subset of their full domain. They are also often concatenated, in the sense of
    combining functions defined on separate domain sets into a combined function defined on the union of those separate domain sets. Those operations would be useful in programs too.

    The essential aspect of maps and map operations is that there is no "sliding" that changes the relationship of domain values (keys) with range values.

    That said, it very often makes sense to provide sorted access to the elements of
    a map, sorted by some criterion, while maintaining the relationship of keys and
    their mapped values. That might be seen as sorting the map into a sequence (as
    described below).

    Perhaps I could have been clearer. I mean that it doesn't make sense to concatenate, sort, slice, or slide an array used as a map. For example, if we represent a map Character => Natural as

    type Char_Count_Map is array (Character) of Natural;
    Map : Char_Count_Map;

    and want a map with the domain restricted to the ASCII letters, both capital and
    small,

    Map ('A' .. 'Z') & Map ('a' ..'z')

    doesn't do what we want.

    You are talking about the abstraction of a map in general, and the operations you describe are different from the array operations I was talking about.

    --
    Jeff Carter
    "[T]he language [Ada] incorporates many excellent structural
    features which have proved their value in many precursor
    languages ..."
    C. A. R. Hoare
    180

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Jeffrey R.Carter on Thu Jun 30 00:07:14 2022
    "Jeffrey R.Carter" <spam.jrcarter.not@spam.acm.org.not> wrote in message news:t9hi0d$1ebn4$1@dont-email.me...
    ...
    Perhaps I could have been clearer. I mean that it doesn't make sense to concatenate, sort, slice, or slide an array used as a map. For example, if
    we represent a map Character => Natural as

    type Char_Count_Map is array (Character) of Natural;
    Map : Char_Count_Map;

    and want a map with the domain restricted to the ASCII letters, both
    capital and small,

    Map ('A' .. 'Z') & Map ('a' ..'z')

    doesn't do what we want.

    You are talking about the abstraction of a map in general, and the
    operations you describe are different from the array operations I was
    talking about.

    Exactly. And this is a general problem with arrays (and with built-in types
    in general): the operations often have no relationship to what it really needed. And even when they do, it is more of a happy accident than something meaningful. It's way better to not have those confusing operations around in the first place.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Niklas Holsti on Thu Jun 30 00:14:28 2022
    "Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message news:ji2q1nFu6qeU1@mid.individual.net...
    ...
    Except if someone invents new abstractions and needs a "raw memory" type
    to implement them.

    Sure, but that should be a rarely used type, and it is best off in a corner, much like Unchecked_Conversion and other unsafe stuff.

    My design for a post-Ada langyage has a "Fixed_Vector" container for the purposes of interfacing; it supports setting component sizes so it should
    match any sort of interface. But most abstractions should be built on top of some sort of bounded or unbounded container. The implementation would spend much of its effort optimizing those basic containers rather than worrying
    about making arrays fast.

    You said something about slices of matrices being a common operation. And I agree with that, and it is one that Ada cannot support. It would be better
    if slices were implemented as a form of function, so that they can be used
    when they make sense (and only then). No reason to build in such things. (My post-Ada language design includes variable-returning functions, so that sort
    of need can be accomadated.)

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Thu Jun 30 00:03:08 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t9h4i9$118a$1@gioia.aioe.org...
    ...
    A language that provided direct support for these abstractions should not
    need to provide arrays.

    Which is of course impossible considering the variety of maps (e.g. graph
    is a map etc) and all problem-space specific.

    Nobody uses arrays to implement graphs anyway. That's something you do when
    you are using a language like Fortran 66 that doesn't have any abstractions.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Thu Jun 30 00:00:34 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t9gunm$97a$1@gioia.aioe.org...
    On 2022-06-29 06:07, Randy Brukardt wrote:
    What you say here is precisely how they should work. But you would make
    the
    cost of supporting that necessary on every array object, because one
    could
    not know when an array is passed as a parameter what sort of
    representation
    it has. So one has to use dispatching helper operations to implement all
    assignments. And that's way more expensive than traditional array
    implementation.

    It is already there because Ada 83 arrays have definite and indefinite representations. Adding a user-defined representation on top is nothing.

    Actually, it changes everything. Array descriptors are easy, indeed, for
    many years Janus/Ada represented all arrays the same (an indefinite representation with a small descriptor containing a pointer at a data area). Changing the representation of the underlying data is where the cost is.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marius Amado-Alves@21:1/5 to All on Thu Jun 30 01:31:03 2022
    "... It would be better if slices were implemented as a form of function, so that they can be used when they make sense... (My post-Ada language design includes variable-returning functions, so that sort of need can be accomadated.)"
    (Randy)

    What is a "variable-returning function"? Is there available material on this post-Ada language design of yours? Thanks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Thu Jun 30 10:44:17 2022
    On 2022-06-30 07:03, Randy Brukardt wrote:
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:t9h4i9$118a$1@gioia.aioe.org...
    ...
    A language that provided direct support for these abstractions should not >>> need to provide arrays.

    Which is of course impossible considering the variety of maps (e.g. graph
    is a map etc) and all problem-space specific.

    Nobody uses arrays to implement graphs anyway.

    It depends on the type of graph and operations on it, high-connectivity
    graphs (incidence matrix) or b-trees (blocks) certainly would use arrays.

    That's something you do when
    you are using a language like Fortran 66 that doesn't have any abstractions.

    But that is unrelated to abstraction. FORTRAN had no access types
    therefore memory management of graph nodes was user-implemented on top
    of large arrays with the array index playing the role of a pointer to
    the node.

    Even if FORTRAN had abstract data types, in order to implement a graph
    datatype you would still have to resort to arrays. It is just different
    things: abstraction does not mean you have it implemented and
    conversely. In Ada we have array implementation, but very limited
    abstraction of:

    1. formal generic arrays
    2. definite/indefinite unification

    Index and aggregate hacks in no way support or extend the abstraction as
    the OP noticed.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Randy Brukardt on Thu Jun 30 12:30:41 2022
    On 2022-06-30 07:14, Randy Brukardt wrote:

    My design for a post-Ada langyage has a "Fixed_Vector" container for the purposes of interfacing; it supports setting component sizes so it should match any sort of interface. But most abstractions should be built on top of some sort of bounded or unbounded container. The implementation would spend much of its effort optimizing those basic containers rather than worrying about making arrays fast.

    You said something about slices of matrices being a common operation. And I agree with that, and it is one that Ada cannot support. It would be better if slices were implemented as a form of function, so that they can be used when they make sense (and only then). No reason to build in such things. (My post-Ada language design includes variable-returning functions, so that sort of need can be accomadated.)

    My thinking along these lines I call King and have described informally at https://github.com/jrcarter/King. Taft's seems to be Parasail (and now Paradiso). Guest has orenda at https://github.com/Lucretia/orenda. Do you have any sort of description or specification of your "post-Ada language"? I would be
    interested in seeing that or learning more about it.

    --
    Jeff Carter
    "Simplicity and elegance are unpopular because
    they require hard work and discipline to
    achieve and education to be appreciated."
    Edsger Dijkstra
    170

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marius Amado-Alves@21:1/5 to All on Thu Jun 30 08:48:15 2022
    My thinking along these lines I call King and have described informally at https://github.com/jrcarter/King. Taft's seems to be Parasail (and now Paradiso). Guest has orenda at https://github.com/Lucretia/orenda. Do you have
    any sort of description or specification of your "post-Ada language"? I would be
    interested in seeing that or learning more about it.
    --
    Jeff Carter

    Wow, I wasn't aware there were so many "post-Ada" thinking! We should make an workshop, maybe at Ada-Europe.

    Jeff, great document (and great name:-) My impression is that it is maybe too much Adaist... except that modules don't have state?! That sounds very limiting to me.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Marius Amado-Alves on Thu Jun 30 18:39:47 2022
    On 2022-06-30 17:48, Marius Amado-Alves wrote:

    Jeff, great document (and great name:-) My impression is that it is maybe too much Adaist... except that modules don't have state?! That sounds very limiting to me.

    I don't know what you mean by "too much Adaist". I have always maintained that Ada 83 is a very good language, and remains a better language than most of the popular languages in use today, so I unashamedly use it as the basis for King, along with lessons learned, good features from later versions of Ada, and some ideas of my own. No software-engineering language will ever be popular, so I see
    no reason to deviate from Ada-like syntax.

    Modules can have state, though in many cases you'd use a module type or passive task.

    --
    Jeff Carter
    "Simplicity and elegance are unpopular because
    they require hard work and discipline to
    achieve and education to be appreciated."
    Edsger Dijkstra
    170

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marius Amado-Alves@21:1/5 to All on Thu Jun 30 17:07:36 2022
    Jeff, sorry, I meant state directly accessible by the client, as modules "cannot contain declarations of variables of
    assignable types in the specification" (Kind doc.)

    An example of Adaism is characters as enumerals.

    But all this should be discussed at the workshop:-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to All on Fri Jul 1 00:20:05 2022
    "Marius Amado-Alves" <amado.alves@gmail.com> wrote in message news:1f894a48-b213-46d8-960f-6e97732e6105n@googlegroups.com...
    "... It would be better if slices were implemented as a form of function,
    so that they can be used when they make sense... (My post-Ada language
    design includes variable-returning functions, so that sort of need can be accomadated.)"
    (Randy)

    What is a "variable-returning function"?

    I've imagined that "variable" and "static" are keywords that can be used
    like "constant" to declare objects. (And "constant" is the default, not variable.)

    Once you have that, it makes sense to allow those in function returns:

    function Foo ... return constant Integer;
    function Bar ... return variable Integer;

    Bar returns a variable, which simply means that you can write into it as
    well as read it. Semantically, it is similar to Ada's anonymous access
    types, except that it isn't an access type, so you can't convert it to one (with all of the loss of checking that implies).

    Is there available material on this post-Ada language design of yours?

    No. It was a pandemic project (when I was essentially stuck at home), and I never made a version for public consumption (I wanted to gather more input
    on it before making it widely available). It's obvious that it would be
    quite time-consuming to do that (and I'm not the best explainer of ideas
    anyway - I tend to ramble... :-). So I never finished it (having gotten too busy completing Ada 2022 work).

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)