• Calling inherited primitive operations in Ada

    From Emmanuel Briot@21:1/5 to All on Wed Aug 31 01:15:38 2022
    A small blog post that you might find interesting:

    https://deepbluecap.com/calling-inherited-primitive-operations-in-ada/

    We are preparing a number of other posts, but right now this is the only one on our web site, so the links are a bit hidden. They will become available on https://deepbluecap.com/blog/ as we publish them.

    Emmanuel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Wed Aug 31 19:11:20 2022
    Le 31/08/2022 à 10:15, Emmanuel Briot a écrit :
    A small blog post that you might find interesting:

    https://deepbluecap.com/calling-inherited-primitive-operations-in-ada/

    We are preparing a number of other posts, but right now this is the only one on our web site, so the links are a bit hidden. They will become available on https://deepbluecap.com/blog/ as we publish them.

    Emmanuel

    That's interesting.

    You should compile all excerpts of code you publish. This will avoid
    typos like "Polgyon" ;)

    Nicolas

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Emmanuel Briot on Wed Aug 31 21:13:14 2022
    On 2022-08-31 10:15, Emmanuel Briot wrote:
    A small blog post that you might find interesting:

    https://deepbluecap.com/calling-inherited-primitive-operations-in-ada/

    This same technique is used in generics to work around another language
    design "feature":

    generic
    type Foo is ...;
    package
    subtype Actual_Foo is Foo;

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Wed Aug 31 23:56:26 2022
    generic
    type Foo is ...;
    package
    subtype Actual_Foo is Foo;

    To me, this is an orthogonal issue though (which would be worth its own blog post in fact). I can never remember (or perhaps not even understand) the reason for this limitation in Ada, which is a major pain when dealing with generics indeed...
    I like the "Actual_" prefix, which I assume is some sort of convention in your code.

    Emmanuel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From amosteo@unizar.es@21:1/5 to briot.e...@gmail.com on Thu Sep 1 00:57:33 2022
    On Thursday, September 1, 2022 at 8:56:28 AM UTC+2, briot.e...@gmail.com wrote:
    generic
    type Foo is ...;
    package
    subtype Actual_Foo is Foo;
    To me, this is an orthogonal issue though (which would be worth its own blog post in fact). I can never remember (or perhaps not even understand) the reason for this limitation in Ada, which is a major pain when dealing with generics indeed...
    I like the "Actual_" prefix, which I assume is some sort of convention in your code.

    Is this about how according to some mystifying rules generic formals are[n't] visible from outside the generic?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to amo...@unizar.es on Thu Sep 1 12:02:43 2022
    On 2022-09-01 09:57, amo...@unizar.es wrote:
    On Thursday, September 1, 2022 at 8:56:28 AM UTC+2, briot.e...@gmail.com wrote:
    generic
    type Foo is ...;
    package
    subtype Actual_Foo is Foo;
    To me, this is an orthogonal issue though (which would be worth its own blog post in fact). I can never remember (or perhaps not even understand) the reason for this limitation in Ada, which is a major pain when dealing with generics indeed...
    I like the "Actual_" prefix, which I assume is some sort of convention in your code.

    Is this about how according to some mystifying rules generic formals are[n't] visible from outside the generic?

    Right. I do not remember the rules, just the fact that they are quite
    logical. Unfortunately the logic of is not very helpful. (:-))

    As for primitive operations the problems are on many levels, from
    lacking introspection to missing inheritance of implementation by
    composition (AKA hooking).

    --
    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 amo...@unizar.es on Thu Sep 1 13:59:29 2022
    On 2022-09-01 09:57, amo...@unizar.es wrote:

    Is this about how according to some mystifying rules generic formals are[n't] visible from outside the generic?

    This seems like a non-issue to me. Any code that has visibility to a generic instance knows the actuals used for that instance. Can anyone provide real examples where this is a problem?

    --
    Jeff Carter
    "[M]any were collected near them, ... to
    enjoy the sight of a dead young lady, nay,
    two dead young ladies, for it proved twice
    as fine as the first report."
    Persuasion
    155

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Jeffrey R.Carter on Thu Sep 1 14:37:36 2022
    On 2022-09-01 13:59, Jeffrey R.Carter wrote:
    On 2022-09-01 09:57, amo...@unizar.es wrote:

    Is this about how according to some mystifying rules generic formals
    are[n't] visible from outside the generic?

    This seems like a non-issue to me. Any code that has visibility to a
    generic instance knows the actuals used for that instance.

    That would make the code fragile. Should be avoided as much as possible
    as a form of aliasing. Compare:

    procedure A (X : Integer) is
    procedure B (Y : Integer) is
    begin
    X := 1; -- We know we are going to call it with X!
    end B;
    begin
    B (X);
    end A;

    Can anyone
    provide real examples where this is a problem?

    Defaulted formal package actual part:

    generic
    package Foo is new Bar (<>);
    package Baz is ...
    -- What were these actuals in Foo?

    This is one of most useful features used to reduce lists of formal
    parameters and simplify instantiations.

    --
    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 Dmitry A. Kazakov on Thu Sep 1 15:37:12 2022
    On 2022-09-01 14:37, Dmitry A. Kazakov wrote:


    Toy problem ignored.

    Can anyone provide real examples where this is a problem?

    Defaulted formal package actual part:

       generic
          package Foo is new Bar (<>);
       package Baz is ...
          -- What were these actuals in Foo?

    1. The actuals of Foo are visible within Baz.
    2. This is not a real example.
    3. You have changed the subject from needing to rename a formal type. I presume this is because there are no real examples where renaming a formal type in an instance is needed.

    --
    Jeff Carter
    "[M]any were collected near them, ... to
    enjoy the sight of a dead young lady, nay,
    two dead young ladies, for it proved twice
    as fine as the first report."
    Persuasion
    155

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Thu Sep 1 07:10:03 2022
    I have seen quite a number of cases of needing the subtype like Dmitry was showing. In a small number of cases, those were actual bugs in GNAT, but most of the time the compiler was correct.
    Mostly, you start to see the issue when you have generic packages that have formal generic packages.

    Here is a quick example and the corresponding compiler error message. In Main, there is no way to see T. Of course, I can use Integer_Signature
    directly, but this is an issue.
    - if I rename Integer_Signature then I have to change a lot of places in my code (The aliasing that Dmitry was talking about)

    with Signature;
    generic
    with package Sign is new Signature (<>);
    package Algo is
    procedure Compute (V : Sign.T) is null;
    end Algo;

    with Algo;
    with Signature;
    package Lib is
    package Integer_Signature is new Signature (Integer);
    package Integer_Algo is new Algo (Integer_Signature);
    end Lib;


    with Lib;
    procedure Main is
    V : Lib.Integer_Algo.Sign.T;
    -- main.adb:3:24: "Sign" is not a visible entity of "Integer_Algo"
    begin
    null;
    end Main;

    generic
    type T is private;
    package Signature is
    end Signature;

    There are more interesting examples, somehow this one doesn't seem that bad. So here is another one:

    generic
    type T is private;
    package Gen is
    end Gen;

    with Gen;
    generic
    type T is private;
    with package Must_Match is new Gen (T);
    with package Need_Not_Match is new Gen (<>);
    package Gen2 is
    V1 : Must_Match.T; -- "T" is not a visible entity of "Must_Match"
    V2 : Need_Not_Match.T; -- instance of same package, but this time T is visible
    end Gen2;

    with Gen, Gen2;
    procedure P2 is
    package G is new Gen (Integer);
    package G2 is new Gen2 (Integer, G, G);
    begin
    null;
    end P2;




    I dug out the explanation that Tucker Taft once sent to the Ada-Comment mailing list (2019-11-14):

    <<<
    10/2
    {AI95-00317-01} The visible part of a formal package includes the first list of basic_declarative_items of the package_specification. In addition, for each actual parameter that is not required to match, a copy of the declaration of the corresponding
    formal parameter of the template is included in the visible part of the formal package. If the copied declaration is for a formal type, copies of the implicit declarations of the primitive subprograms of the formal type are also included in the visible
    part of the formal package.
    10.a/2
    Ramification: {AI95-00317-01} If the formal_package_actual_part is (<>), then the declarations that occur immediately within the generic_formal_part of the template for the formal package are visible outside the formal package, and can be denoted by
    expanded names outside the formal package.If only some of the actual parameters are given by <>, then the declaration corresponding to those parameters (but not the others) are made visible.
    10.b/3
    Reason: {AI05-0005-1} We always want either the actuals or the formals of an instance to be nameable from outside, but never both. If both were nameable, one would get some funny anomalies since they denote the same entity, but, in the case of types at
    least, they might have different and inconsistent sets of primitive operators due to predefined operator “reemergence.” Formal derived types exacerbate the difference. We want the implicit declarations of the generic_formal_part as well as the
    explicit declarations, so we get operations on the formal types.


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From amosteo@unizar.es@21:1/5 to briot.e...@gmail.com on Thu Sep 1 08:50:21 2022
    On Thursday, September 1, 2022 at 4:11:54 PM UTC+2, briot.e...@gmail.com wrote:
    I have seen quite a number of cases of needing the subtype like Dmitry was showing. In a small number of cases, those were actual bugs in GNAT, but most of the time the compiler was correct.
    Mostly, you start to see the issue when you have generic packages that have formal generic packages.

    This matches exactly my experience. I don't have enough grasp of the details to come up with a realistic short example, but I did hit this issue pretty often in two libs were I used signature packages quite extensively:

    https://github.com/mosteo/rxada
    https://github.com/mosteo/iterators

    Initially I was always under the impression I was hitting GNAT bugs but then it turned out there were rules about it. A couple example places (you can see the renamings at the top. I was adding them "on demand" so to say):

    https://github.com/mosteo/iterators/blob/master/src/iterators-traits-containers.ads
    https://github.com/mosteo/rxada/blob/master/src/priv/rx-impl-transformers.ads

    Thanks Emmanuel for the examples and digging out Tucker explanation.

    -Alex.

    There are more interesting examples, somehow this one doesn't seem that bad. So here is another one:

    generic
    type T is private;
    package Gen is
    end Gen;

    with Gen;
    generic
    type T is private;
    with package Must_Match is new Gen (T);
    with package Need_Not_Match is new Gen (<>);
    package Gen2 is
    V1 : Must_Match.T; -- "T" is not a visible entity of "Must_Match"
    V2 : Need_Not_Match.T; -- instance of same package, but this time T is visible
    end Gen2;

    with Gen, Gen2;
    procedure P2 is
    package G is new Gen (Integer);
    package G2 is new Gen2 (Integer, G, G);
    begin
    null;
    end P2;




    I dug out the explanation that Tucker Taft once sent to the Ada-Comment mailing list (2019-11-14):

    <<<
    10/2
    {AI95-00317-01} The visible part of a formal package includes the first list of basic_declarative_items of the package_specification. In addition, for each actual parameter that is not required to match, a copy of the declaration of the corresponding
    formal parameter of the template is included in the visible part of the formal package. If the copied declaration is for a formal type, copies of the implicit declarations of the primitive subprograms of the formal type are also included in the visible
    part of the formal package.
    10.a/2
    Ramification: {AI95-00317-01} If the formal_package_actual_part is (<>), then the declarations that occur immediately within the generic_formal_part of the template for the formal package are visible outside the formal package, and can be denoted by
    expanded names outside the formal package.If only some of the actual parameters are given by <>, then the declaration corresponding to those parameters (but not the others) are made visible.
    10.b/3
    Reason: {AI05-0005-1} We always want either the actuals or the formals of an instance to be nameable from outside, but never both. If both were nameable, one would get some funny anomalies since they denote the same entity, but, in the case of types at
    least, they might have different and inconsistent sets of primitive operators due to predefined operator “reemergence.” Formal derived types exacerbate the difference. We want the implicit declarations of the generic_formal_part as well as the
    explicit declarations, so we get operations on the formal types.


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to Jeffrey R.Carter on Thu Sep 1 09:07:09 2022
    On Thursday, September 1, 2022 at 6:03:22 PM UTC+2, Jeffrey R.Carter wrote:
    This is true in all these examples. I have used Ada since 1984, and this has never been a problem for me (as initially presented, this would have existed in

    So basically saying that you do not use generics (or only very basic versions) and you have never seen
    the bug that relates to complex generics. Not very useful input ?
    For sure, that's already a number of persons who have said they have seen this bug a number of times.
    I have of course only been using Ada for 25 years, but that sure was enough to see that issue...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Emmanuel Briot on Thu Sep 1 18:03:19 2022
    On 2022-09-01 16:10, Emmanuel Briot wrote:
    I have seen quite a number of cases of needing the subtype like Dmitry was showing. In a small number of cases, those were actual bugs in GNAT, but most of the time the compiler was correct.
    Mostly, you start to see the issue when you have generic packages that have formal generic packages.

    None of these deal with the example I responded to

    generic
    type T is ...
    package P is
    subtype Actual_T is T;

    Reason: {AI05-0005-1} We always want either the actuals or the formals of an instance to be nameable from outside, but never both.
    This is true in all these examples. I have used Ada since 1984, and this has never been a problem for me (as initially presented, this would have existed in Ada 83). Of course, I generally avoid generic formal pkgs. They seem to me to be
    a work around for poor design, and I prefer to correct the design.

    --
    Jeff Carter
    "[M]any were collected near them, ... to
    enjoy the sight of a dead young lady, nay,
    two dead young ladies, for it proved twice
    as fine as the first report."
    Persuasion
    155

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Emmanuel Briot on Thu Sep 1 18:17:06 2022
    On 2022-09-01 18:07, Emmanuel Briot wrote:

    So basically saying that you do not use generics (or only very basic versions) and you have never seen
    the bug that relates to complex generics. Not very useful input ?

    I have not said this. I have worked on very large problems and on generics appropriate to such problems. Of course, KISS is an important S/W-eng principle.

    --
    Jeff Carter
    "[M]any were collected near them, ... to
    enjoy the sight of a dead young lady, nay,
    two dead young ladies, for it proved twice
    as fine as the first report."
    Persuasion
    155

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Thu Sep 1 11:54:00 2022
    I think I have a more interesting example. This one is extracted from my attempted traits containers, for which I had published a blog post at AdaCore. My enhanced fork of the library is at
    https://github.com/briot/ada-traits-containers
    if someone wants to experiment with non-trivial generics code (and containers are of course a case where generics fully make sense).

    Here is the example:

    generic
    type Element_Type is private;
    type Stored_Type is private;
    package Elements is
    end Elements;

    with Elements;
    generic
    type Element_Type is private;
    package Definite_Elements is
    package Traits is new Elements (Element_Type, Stored_Type => Element_Type); end Definite_Elements;

    with Definite_Elements;
    generic
    type Key_Type is private;
    package Maps is
    package Keys is new Definite_Elements (Key_Type);
    function "=" (L, R : Keys.Traits.Stored_Type) return Boolean -- "Stored_Type" is not a visible entity of "Traits"
    is (False);
    end Maps;


    This is not case where the actual is visible unless I happen to know how Definite_Element is implemented and that it will use Element_Type for Stored_Type (and this is not a knowledge I wish client packages to have, the whole point of Element and
    Definite_Element is to basically hide how elements can be stored in a container, and whether we need memory allocation for instance).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Emmanuel Briot on Thu Sep 1 23:33:44 2022
    On 2022-09-01 20:54, Emmanuel Briot wrote:

    generic
    type Element_Type is private;
    type Stored_Type is private;
    package Elements is
    end Elements;

    with Elements;
    generic
    type Element_Type is private;
    package Definite_Elements is
    package Traits is new Elements (Element_Type, Stored_Type => Element_Type);
    end Definite_Elements;

    with Definite_Elements;
    generic
    type Key_Type is private;
    package Maps is
    package Keys is new Definite_Elements (Key_Type);
    function "=" (L, R : Keys.Traits.Stored_Type) return Boolean -- "Stored_Type" is not a visible entity of "Traits"
    is (False);
    end Maps;

    As presented, this seems very over complicated. Elements and Definite_Elements add no value, and this is just a complex way of writing

    generic
    type Key is private;
    package Maps is
    function "=" (L : in Key; R : in Key) return Boolean is (False);
    end Maps;

    One hopes that the actual library makes better use of these pkgs than this small
    example.

    This is not case where the actual is visible unless I happen to know how Definite_Element is implemented and that it will use Element_Type for Stored_Type (and this is not a knowledge I wish client packages to have, the whole point of Element and
    Definite_Element is to basically hide how elements can be stored in a container, and whether we need memory allocation for instance).

    Ada has excellent features for hiding, but these are not among them. Assuming that pkg Keys serves some actual role in the spec of Maps, then someone wanting to use pkg Maps will need to understand that role, which involves understanding Definite_Elements, which involves understanding pkg Traits, which involves understanding Elements. Rather than hiding anything, you are effectively requiring your users to look at these things, even if you could use the notation
    in question.

    --
    Jeff Carter
    "[M]any were collected near them, ... to
    enjoy the sight of a dead young lady, nay,
    two dead young ladies, for it proved twice
    as fine as the first report."
    Persuasion
    155

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Thu Sep 1 23:11:45 2022
    As presented, this seems very over complicated. Elements and Definite_Elements
    add no value, and this is just a complex way of writing

    I did point you to the full repository if you prefer an extensive, real-life code sample. This was just an extract showing the gist of the issue.

    One hopes that the actual library makes better use of these pkgs than this small
    example.

    One can check the full code and extensive documentation on the design in the github repository.
    This is called code reuse, was invented quite a while ago.
    These packages are mostly implementation details. They are used to build high-level packages similar to the Ada containers, except with much better code reuse, more efficient, and SPARK-provable.

    Ada has excellent features for hiding, but these are not among them. Assuming

    And that's exactly our point in this discussion. Ada on the whole is very good (we would not be using it otherwise), but it does have a number of limitations which are sometimes a pain, this being one of them. Not acknowledging the limitations when they
    exist is naive, all languages have them.

    that pkg Keys serves some actual role in the spec of Maps, then someone wanting
    to use pkg Maps will need to understand that role, which involves understanding
    Definite_Elements, which involves understanding pkg Traits, which involves understanding Elements.

    which involves understanding Ada, which involves understanding the compiler, which involves understanding the kernel sources, ...
    How many times have you checked the whole sources of the GNAT runtime to understand how they implemented the Ada containers ?

    Emmanuel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From amosteo@unizar.es@21:1/5 to Jeffrey R.Carter on Fri Sep 2 01:35:11 2022
    On Thursday, September 1, 2022 at 11:33:47 PM UTC+2, Jeffrey R.Carter wrote:
    On 2022-09-01 20:54, Emmanuel Briot wrote:

    As presented, this seems very over complicated. Elements and Definite_Elements
    add no value, and this is just a complex way of writing

    Going in a tangent, and I guess you know perfectly well, but this is caused by the painful duplication of code that Ada pushes you to by not having a native way to abstract storage of definite vs indefinite types. So the provider of a generic library
    very soon faces this conundrum about duplicating most interfaces, if not implementations, or resort to non-trivial generics, or accept an unnecessary penalty for definite types, or push to the client the definite storage matter. There's simply no
    satisfying solution here [that I know of]. The duplication of every standard container to have both [in]definite variants is a strong indictment.

    I can understand the desire to have full control of allocation and object sizes, but that there's not a language way to work around this duplication, with appropriate restrictions to go with it, is... bothersome. Not making a dig at the ARG, which I
    understand is overstretched as it is.

    There was a proposal circulating some time ago that seemed promising, that I can't quickly find. Something like

    type Blah is record
    Dont_care_if_in_heap: new Whatever_Definiteness; -- Would apply to indefinite types or formals
    end record;

    I don't think it made into https://github.com/AdaCore/ada-spark-rfcs/ or https://github.com/Ada-Rapporteur-Group/User-Community-Input/issues or I can't find it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to amo...@unizar.es on Fri Sep 2 10:48:53 2022
    On 2022-09-02 10:35, amo...@unizar.es wrote:
    On Thursday, September 1, 2022 at 11:33:47 PM UTC+2, Jeffrey R.Carter wrote:
    On 2022-09-01 20:54, Emmanuel Briot wrote:

    As presented, this seems very over complicated. Elements and Definite_Elements
    add no value, and this is just a complex way of writing

    Going in a tangent, and I guess you know perfectly well, but this is caused by the painful duplication of code that Ada pushes you to by not having a native way to abstract storage of definite vs indefinite types. So the provider of a generic library
    very soon faces this conundrum about duplicating most interfaces, if not implementations, or resort to non-trivial generics, or accept an unnecessary penalty for definite types, or push to the client the definite storage matter. There's simply no
    satisfying solution here [that I know of]. The duplication of every standard container to have both [in]definite variants is a strong indictment.

    I can understand the desire to have full control of allocation and object sizes, but that there's not a language way to work around this duplication, with appropriate restrictions to go with it, is... bothersome. Not making a dig at the ARG, which I
    understand is overstretched as it is.

    Containers should be implementable without generics. Just saying.

    There was a proposal circulating some time ago that seemed promising, that I can't quickly find. Something like

    type Blah is record
    Dont_care_if_in_heap: new Whatever_Definiteness; -- Would apply to indefinite types or formals
    end record;

    I would prefer constraint propagation/management support + tuples instead:

    type Blah (Parameters : Whatever_Definiteness'Constraints) is
    Sill_Care : Whatever_Definiteness (Parameters);
    end record;

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From amosteo@unizar.es@21:1/5 to Dmitry A. Kazakov on Fri Sep 2 02:20:44 2022
    On Friday, September 2, 2022 at 10:48:57 AM UTC+2, Dmitry A. Kazakov wrote:

    Containers should be implementable without generics. Just saying.

    Are you now referring to current Ada or to hypothetical features?

    I would prefer constraint propagation/management support + tuples instead:

    type Blah (Parameters : Whatever_Definiteness'Constraints) is
    Sill_Care : Whatever_Definiteness (Parameters);
    end record;

    Whatever ;-) as long as it's an effective solution.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to amo...@unizar.es on Fri Sep 2 11:55:11 2022
    On 2022-09-02 11:20, amo...@unizar.es wrote:
    On Friday, September 2, 2022 at 10:48:57 AM UTC+2, Dmitry A. Kazakov wrote:

    Containers should be implementable without generics. Just saying.

    Are you now referring to current Ada or to hypothetical features?

    Hypothetical like all types having classes and supertypes. E.g. when you instantiate generic with a type you semantically place the type in the
    implicit class of formal types of the generic. You cannot do that now
    without generics. Furthermore, there is no way to describe relationships between types like array index and array, like range and discrete type
    of its elements etc.

    --
    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 Fri Sep 2 13:04:34 2022
    On 2022-09-02 12:41, Jeffrey R.Carter wrote:

    The only indefinite data structure that is needed seems to be holders.

    The language should support and encourage design that does not rely on
    memory pools.

    In my view one of major advantages of Ada is that indefinite objects can
    be handled without resorting to hidden or explicit pointers to pools.

    --
    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 amo...@unizar.es on Fri Sep 2 12:41:42 2022
    On 2022-09-02 10:35, amo...@unizar.es wrote:

    Going in a tangent, and I guess you know perfectly well, but this is caused by the painful duplication of code that Ada pushes you to by not having a native way to abstract storage of definite vs indefinite types. So the provider of a generic library
    very soon faces this conundrum about duplicating most interfaces, if not implementations, or resort to non-trivial generics, or accept an unnecessary penalty for definite types, or push to the client the definite storage matter. There's simply no
    satisfying solution here [that I know of]. The duplication of every standard container to have both [in]definite variants is a strong indictment.

    The only indefinite data structure that is needed seems to be holders. Any other
    indefinite data structure can be implemented as the equivalent definite data structure of holders, so there need be no duplication of implementations. That one cannot use a single pkg for both does result in duplication of the spec, but
    that seems like less of an issue to me.

    --
    Jeff Carter
    "Apple juice and Darvon is fantastic together."
    Play It Again, Sam
    127

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Emmanuel Briot on Fri Sep 2 12:55:13 2022
    On 2022-09-02 08:11, Emmanuel Briot wrote:

    I did point you to the full repository if you prefer an extensive, real-life code sample. This was just an extract showing the gist of the issue.

    One can check the full code and extensive documentation on the design in the github repository.

    Yes, I looked at it, and found it over complicated, difficult to understand, and
    not user friendly. There appears to be extensive HTML documentation, but it can only be viewed as HTML source in Github, which is not easy to read, so I didn't.

    Apparently a user who wants a map has to supply a significant part of what I consider the implementation of the map. As such, this may serve as a hidden layer to implement a library of data structures, but seems unusable for the typical user, for whom using a hashed-map abstraction should be as simple as

    function Hash (Key : in Identifier) return Hash_Value;

    package Maps is new Lib.Maps
    (Identifier => Identifier, Associated_Value => Associated_Value);

    I was not willing to spend more than about 15 minutes trying to understand this,
    so I may be missing something.

    These packages are mostly implementation details. They are used to build high-level packages similar to the Ada containers

    This agrees with what I was saying earlier. But even for such a use, simplicity and ease of understanding are still the most important aspects of S/W. If attaining them involves some code duplication they are worth that price.

    that pkg Keys serves some actual role in the spec of Maps, then someone wanting
    to use pkg Maps will need to understand that role, which involves understanding
    Definite_Elements, which involves understanding pkg Traits, which involves >> understanding Elements.

    which involves understanding Ada, which involves understanding the compiler, which involves understanding the kernel sources, ...
    How many times have you checked the whole sources of the GNAT runtime to understand how they implemented the Ada containers ?

    One understands a pkg by understanding its spec. I find it hard to believe that you could actually think that I meant one had to understand the implementation as well.

    --
    Jeff Carter
    "Apple juice and Darvon is fantastic together."
    Play It Again, Sam
    127

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Fri Sep 2 04:20:38 2022
    not user friendly. There appears to be extensive HTML documentation, but it can
    only be viewed as HTML source in Github, which is not easy to read, so I didn't.

    Those are generated from the .rst files in docs_src/

    typical user, for whom using a hashed-map abstraction should be as simple as

    function Hash (Key : in Identifier) return Hash_Value;
    package Maps is new Lib.Maps
    (Identifier => Identifier, Associated_Value => Associated_Value);

    Maps are created as

    package Maps0 is new GAL.Maps.Def_Def_Unbounded
    (Integer,
    Element_Type => Integer,
    Hash => Test_Support.Hash,
    Container_Base_Type => GAL.Controlled_Base);

    The only addition here is `Container_Base_Type`, and that's because the library is probable with SPARK, and the latter doesn't support controlled types.
    And Ada doesn't support default values for the formal parameters of generics (another annoying limitation !)

    I was not willing to spend more than about 15 minutes trying to understand this,
    so I may be missing something.

    Fair enough. The library is really a set of experiments, mostly successful, and I think it might have been used for the implementation of the current
    SPARK containers in GNAT, though I am not positive there.
    I did look at the pragmARC components, and there you indeed chose to have a large number of similar-looking packages and code duplication. I guess
    we'll have just to agree to disagree on the design approach there. But of course, users having choices is what makes an ecosystem interesting.

    What I was really going after are graphs and their algorithms. In particular, I want those algorithms to work on any graph data structure provided it has
    a number of primitive operations. In fact, the algorithm could also work when the graph is kind of implicit in the code, even if we do not have an actual
    Graph object. And those this, you need generics.

    A similar approach is what Rust uses all over the place with its traits, or what C++ Boost library uses for its graphs, too.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Emmanuel Briot on Fri Sep 2 16:28:43 2022
    On 2022-09-02 13:20, Emmanuel Briot wrote:

    Maps are created as

    package Maps0 is new GAL.Maps.Def_Def_Unbounded
    (Integer,
    Element_Type => Integer,
    Hash => Test_Support.Hash,
    Container_Base_Type => GAL.Controlled_Base);

    Where is that? All I saw in my quick look were Maps, Maps.Generics, and Maps.Impl.

    --
    Jeff Carter
    "Apple juice and Darvon is fantastic together."
    Play It Again, Sam
    127

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Jeffrey R.Carter on Fri Sep 2 19:01:28 2022
    "amo...@unizar.es" <amosteo@unizar.es> wrote in message news:672e9bc6-1e53-42cb-a339-9230ab949de9n@googlegroups.com...
    On Thursday, September 1, 2022 at 11:33:47 PM UTC+2, Jeffrey R.Carter wrote:
    On 2022-09-01 20:54, Emmanuel Briot wrote:

    As presented, this seems very over complicated. Elements and
    Definite_Elements
    add no value, and this is just a complex way of writing

    Going in a tangent, and I guess you know perfectly well, but this is caused >by the
    painful duplication of code that Ada pushes you to by not having a native
    way to
    abstract storage of definite vs indefinite types.

    This is premature optimization at it's worst.

    So the provider of a generic library very soon faces this conundrum about duplicating most interfaces, if not implementations, or resort to
    non-trivial
    generics, or accept an unnecessary penalty for definite types, or push to
    the client the definite storage matter.

    There is no penalty in a code sharing implementation like Janus/Ada: the implementation of definite types is essentially the same as you would write
    by hand for an indefinite type. In most cases, all one needs is an
    indefinite generic.

    (The plan for Janus/Ada was always to use post-compilation optimization to reduce the overhead of generics, but admittedly, that part never got built.
    If I had infinite time...)

    Assuming otherwise is certainly premature optimization.

    There's simply no satisfying solution here [that I know of]. The
    duplication of
    every standard container to have both [in]definite variants is a strong indictment.

    The original expectation for the containers was that there would be many variants of each container, because the needs for memory management, task management, and persistence differ between applications: there is no
    one-size fits all solution.

    But I agree on one point: the "basic" container is unncessary; one should either use the indefinite or bounded container (depending on your memory management needs, either fully fixed or fully heap-based) -- stopping in the middle makes little sense.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to All on Fri Sep 2 19:07:27 2022
    "Emmanuel Briot" <briot.emmanuel@gmail.com> wrote in message news:b678b499-0cb1-4c64-a88f-cfa9a79893e6n@googlegroups.com...

    These packages are mostly implementation details. They are used to build >high-level
    packages similar to the Ada containers, except with much better code reuse, >more
    efficient, and SPARK-provable.

    (Wading in where I should probably not tread... :-)

    But they violate the #1 principle of the Ada.Containers: ease of use. One principle that we insisted on was that a single instantiation was the
    maximum we would use, because we did not want people moving from arrays to containers to have to replace one declaration with a half page of magic incantations. (This is the reason that there is no container interface, for
    one consequence, and certainly no signature packages.)

    In general, people either undertand and like signature packages, or really
    do not understand them and just use them when insisted on. The standard containers in Ada needed to be usable by the maximum number of users, and insisting on bells and whistles that many don't understand does not help.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Fri Sep 2 19:12:25 2022
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:teso01$16gg$1@gioia.aioe.org...
    On 2022-09-02 12:41, Jeffrey R.Carter wrote:

    The only indefinite data structure that is needed seems to be holders.

    The language should support and encourage design that does not rely on
    memory pools.

    In my view one of major advantages of Ada is that indefinite objects can
    be handled without resorting to hidden or explicit pointers to pools.

    But they're implemented with some sort of hidden allocation. (GNAT uses a "secondary stack", whatever that is, but that is just a restricted form of pool). Janus/Ada uses built-in pools with cleanup for all such things to simplify the interface (the code for allocations and stand-alone objects is mostly shared, both within the compiler and at runtime).

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to All on Fri Sep 2 19:16:34 2022
    "Emmanuel Briot" <briot.emmanuel@gmail.com> wrote in message news:bf352372-632c-45c1-b691-758756e87541n@googlegroups.com...
    ...
    And Ada doesn't support default values for the formal parameters of
    generics (another annoying limitation !)

    Ada *DOES* support default values for formal parameters of generics. At
    least the most used kinds of parameters, including subprograms and types
    (the latter added in Ada 2022). Whether GNAT (or your other favorite
    compiler) supports formal type defaults yet is a different question.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Randy Brukardt on Sat Sep 3 10:23:01 2022
    On 2022-09-03 02:12, Randy Brukardt wrote:
    "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:teso01$16gg$1@gioia.aioe.org...
    On 2022-09-02 12:41, Jeffrey R.Carter wrote:

    The only indefinite data structure that is needed seems to be holders.

    The language should support and encourage design that does not rely on
    memory pools.

    In my view one of major advantages of Ada is that indefinite objects can
    be handled without resorting to hidden or explicit pointers to pools.

    But they're implemented with some sort of hidden allocation. (GNAT uses a "secondary stack", whatever that is, but that is just a restricted form of pool). Janus/Ada uses built-in pools with cleanup for all such things to simplify the interface (the code for allocations and stand-alone objects is mostly shared, both within the compiler and at runtime).

    For a programmer that does not matter. The problem with pools is
    locking, non-determinism, issues with protected actions. If secondary or primary stack is the program stack, nobody really cares.

    BTW, merely doing pool tracing/bookkeeping becomes a sheer nightmare if
    you cannot return a string from a function.

    --
    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 Sat Sep 3 10:59:16 2022
    On 2022-09-03 02:07, Randy Brukardt wrote:

    One
    principle that we insisted on was that a single instantiation was the
    maximum we would use

    Except for queues

    --
    Jeff Carter
    "In our experiments, the [Ada] compile[r] was able to find not
    just typographical errors, but also conceptual errors in the
    development of the code."
    Scott and Bagheri
    161

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Wright@21:1/5 to Randy Brukardt on Sat Sep 3 20:00:00 2022
    "Randy Brukardt" <randy@rrsoftware.com> writes:

    But they violate the #1 principle of the Ada.Containers: ease of
    use. One principle that we insisted on was that a single instantiation
    was the maximum we would use

    And this was one reason that I didn't put up any arguments at Ada Europe
    2002 for the Ada 95 Booch Components to form a basis for Ada.Containers
    - you'd need 3 instantiations, one after the other.

    -- A company's Fleet holds a number of Cars.

    with BC.Containers.Collections.Bounded;
    with Cars;
    package My_Fleet is

    use type Cars.Car;

    package Abstract_Car_Containers
    is new BC.Containers (Cars.Car);

    package Abstract_Car_Collections
    is new Abstract_Car_Containers.Collections;

    package Fleets
    is new Abstract_Car_Collections.Bounded (Maximum_Size => 30);

    The_Fleet : Fleets.Collection;

    end My_Fleet;

    The other was a lack of consistency in the implementation (Length?
    Size?).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Sun Sep 4 23:56:43 2022
    Jeff Carter:
    Where is that? All I saw in my quick look were Maps, Maps.Generics, and Maps.Impl.

    Simon Wright:
    And this was one reason that I didn't put up any arguments at Ada Europe
    2002 for the Ada 95 Booch Components to form a basis for Ada.Containers
    - you'd need 3 instantiations, one after the other.

    I definitely see the same issue. The way my library is trying to workaround that is as follows:
    Those instantiations are only needed for people who want/need to control every aspects of their containers, for instance
    how elements are stored, how/when memory is allocated, what is the growth strategy for vectors, and so on.
    Most users should not have to care about that in practice. So we use code generation at compile time to generate
    high-level packages similar to the Ada containers, with a limited set of formal parameters (in src/generated, to be
    more specific). We can generate bounded/unbounded versions, definite/indefinite versions, and any combination of
    those.
    One of the intentions of the library, initially, had been the implementation of the Ada containers and SPARK containers
    in GNAT, as a way to share as much code as possible between the two.


    Randy Brukardt:
    Assuming otherwise is certainly premature optimization.

    I am quoting a bit out of context, though I believe it is close enough. Designers of containers must care about performance
    from the get-go. Otherwise, people might just as well use a list for everything and just traverse the list all the time. We all
    know this would be way too inefficient, of course, which is why there are various sorts of containers.
    Anyone who has actually written performance-sensitive code knows that memory allocations is definitely something to watch
    out for, and the library design should definitely take that into account.

    Jeff Carter:
    The only indefinite data structure that is needed seems to be holders

    Although it is certainly true that using holders works, it is not applicable when designing a containers library that intends to be
    mostly compatible with Ada containers. The latter have chosen, long ago and before Holder was a thing, to have definite and
    indefinite versions. The main benefit to this approach is that users still retrieve directly the type they are interested in (e.g. String)
    rather than a holder-to-string.
    I must admit I have very limited experience with Holders, which I have never used in production code (nor, apparently, have my
    colleagues and ex-colleagues).


    Randy Brukardt:
    Ada *DOES* support default values for formal parameters of generics

    Hey, I just discovered that, thanks Randy ! For people who also did not know that:

    generic
    type Item_Count is range <> or use Natural;
    package Gen is

    It is supported by GNAT's newer versions (I don't know when it was implemented though)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Emmanuel Briot on Mon Sep 5 09:34:37 2022
    On 2022-09-05 08:56, Emmanuel Briot wrote:

    Although it is certainly true that using holders works, it is not applicable when designing a containers library that intends to be
    mostly compatible with Ada containers.

    Right. Holder requires finalization and finalization means language
    prescribed finalization lists which is highly undesirable in many cases.

    The main benefit to this approach is that users still retrieve directly the type they are interested in (e.g. String)
    rather than a holder-to-string.

    And that the container designer has control over the pool where the
    items get actually allocated.

    I must admit I have very limited experience with Holders, which I have never used in production code (nor, apparently, have my
    colleagues and ex-colleagues).

    I have been using the idea for a long time, since Ada 95 before the
    standard library had them. In my experience holders multiply the number
    of container variants:

    1. Definite elements
    2. Indefinite elements
    +
    3. Holder elements in the interface (and maybe implementation)

    The third gets a holder package as a formal parameter or, alternatively,
    is a child of a holder package (for performance reasons). The container interface has direct operations in terms of the Element_Type as well as
    in terms of the holder type.

    Sometimes the holder variant is actually the indefinite one that
    promotes holders only in its interface.

    P.S. In my opinion helper types/package is an evil of far greater scale
    than any premature optimization!

    The programmers doing the latter at least try to understand the code
    they write.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From amosteo@unizar.es@21:1/5 to Randy Brukardt on Mon Sep 5 01:53:19 2022
    On Saturday, September 3, 2022 at 2:01:32 AM UTC+2, Randy Brukardt wrote:
    "amo...@unizar.es" <amo...@unizar.es> wrote in message news:672e9bc6-1e53-42cb...@googlegroups.com...
    On Thursday, September 1, 2022 at 11:33:47 PM UTC+2, Jeffrey R.Carter wrote:
    On 2022-09-01 20:54, Emmanuel Briot wrote:

    As presented, this seems very over complicated. Elements and
    Definite_Elements
    add no value, and this is just a complex way of writing

    Going in a tangent, and I guess you know perfectly well, but this is caused >by the
    painful duplication of code that Ada pushes you to by not having a native >way to
    abstract storage of definite vs indefinite types.

    This is premature optimization at it's worst.

    Just because the language doesn't offer a way to do it. Otherwise I wouldn't need to care.

    So the provider of a generic library very soon faces this conundrum about duplicating most interfaces, if not implementations, or resort to non-trivial
    generics, or accept an unnecessary penalty for definite types, or push to the client the definite storage matter.
    There is no penalty in a code sharing implementation like Janus/Ada: the implementation of definite types is essentially the same as you would write by hand for an indefinite type. In most cases, all one needs is an
    indefinite generic.

    Well, that sounds neat for Janus/Ada, but is a different issue to clients having to wrap their indefinite types prior to instantiation, and suffer the unwrapping throughout the code.

    (The plan for Janus/Ada was always to use post-compilation optimization to reduce the overhead of generics, but admittedly, that part never got built. If I had infinite time...)

    Assuming otherwise is certainly premature optimization.

    I'm of the opinion that it goes beyond just premature optimization, in the terrain of readability/maintainability by causing boilerplate, and when generics specializations do become necessary, by causing code duplication.

    There's simply no satisfying solution here [that I know of]. The duplication of
    every standard container to have both [in]definite variants is a strong indictment.
    The original expectation for the containers was that there would be many variants of each container, because the needs for memory management, task management, and persistence differ between applications: there is no
    one-size fits all solution.

    But I agree on one point: the "basic" container is unncessary; one should either use the indefinite or bounded container (depending on your memory management needs, either fully fixed or fully heap-based) -- stopping in the middle makes little sense.

    That makes sense, right.


    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From amosteo@unizar.es@21:1/5 to amo...@unizar.es on Mon Sep 5 01:56:40 2022
    On Monday, September 5, 2022 at 10:53:21 AM UTC+2, amo...@unizar.es wrote:
    On Saturday, September 3, 2022 at 2:01:32 AM UTC+2, Randy Brukardt wrote:

    Well, that sounds neat for Janus/Ada, but is a different issue to clients having to wrap their indefinite types prior to instantiation, and suffer the unwrapping throughout the code.

    Drats, I was here obviously thinking about the contrary case where only the definite container exists...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Emmanuel Briot on Mon Sep 5 11:30:56 2022
    On 2022-09-05 08:56, Emmanuel Briot wrote:

    I definitely see the same issue. The way my library is trying to workaround that is as follows:
    Those instantiations are only needed for people who want/need to control every aspects of their containers, for instance
    how elements are stored, how/when memory is allocated, what is the growth strategy for vectors, and so on.
    Most users should not have to care about that in practice. So we use code generation at compile time to generate
    high-level packages similar to the Ada containers, with a limited set of formal parameters (in src/generated, to be
    more specific). We can generate bounded/unbounded versions, definite/indefinite versions, and any combination of
    those.

    This seems backwards. The user should encounter the forms most likely to be used
    first; if part of the packages are in a subdirectory, those should be the ones less likely for the typical user to use.

    Although it is certainly true that using holders works, it is not applicable when designing a containers library that intends to be
    mostly compatible with Ada containers. The latter have chosen, long ago and before Holder was a thing, to have definite and
    indefinite versions. The main benefit to this approach is that users still retrieve directly the type they are interested in (e.g. String)
    rather than a holder-to-string.

    Before Ada.Containers existed, I commonly used definite data structures from the
    PragmARCs with Unbounded_String, which is partly a specialized holder for String
    (and partly a specialized Vector for Positive/Character). Generalizing from this
    led to implementing a Holder pkg.

    When I said a holder is the only indefinite pkg that is needed, I meant to imply
    that other indefinite structures would be implemented using the definite form + holder.

    --
    Jeff Carter
    “Bug rates in C++ are running higher even than C ...”
    Stephen F. Zeigler
    216

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to All on Tue Sep 6 19:51:44 2022
    "Emmanuel Briot" <briot.emmanuel@gmail.com> wrote in message news:458444ed-e384-4663-896c-bb38dae3c5cbn@googlegroups.com...
    ...
    Randy Brukardt:
    Assuming otherwise is certainly premature optimization.

    I am quoting a bit out of context, though I believe it is close enough. Designers of containers must care about performance
    from the get-go. Otherwise, people might just as well use a list for everything and just traverse the list all the time. We all
    know this would be way too inefficient, of course, which is why there
    are various sorts of containers. Anyone who has actually written performance-sensitive code knows that memory allocations is definitely something to watch out for, and the library design should definitely take that into account.

    Definitely out of context. If you have code which is truly performance sensitive, then it cannot also be portable Ada code. That's because of the
    wide variety of implementation techniques, especially for generics. (For Janus/Ada, if you have critical performance needs, you have to avoid the use
    of generics in those critical paths -- sharing overhead is non-zero.)

    I agree that the design of the containers matters (which is why the we made
    the sets of operations for the various containers as close as possible, so switching containers is relatively easy). But the indefinite/definite thing
    is premature optimization - it makes little difference for a Janus/Ada
    generic, at least in the absence of the full-program optimizer (that we
    never built). If your code isn't intended to be portable Ada code, then
    *maybe* it makes sense to worry about such things. But the expectation was always that containers would be useful in cases where the performance is
    *not* critical - one probably should use a custom data structure for performance critical things. (But most things aren't really performance critical in reality.)

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Jeffrey R.Carter on Tue Sep 6 19:42:57 2022
    "Jeffrey R.Carter" <spam.jrcarter.not@spam.acm.org.not> wrote in message news:tev515$2rbj5$1@dont-email.me...
    On 2022-09-03 02:07, Randy Brukardt wrote:

    One
    principle that we insisted on was that a single instantiation was the
    maximum we would use

    Except for queues

    Right, and one consequence of that is that the queues aren't used much. (Not sure if they would be used much in any case, they're definitely a
    specialized need compared to a map.)

    Randy.

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