comp.lang.ada
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: Aggregate with derived types.
  2023-09-14 15:31  0% ` Jeffrey R.Carter
@ 2023-09-14 20:00  0%   ` Blady
  0 siblings, 0 replies; 200+ results
From: Blady @ 2023-09-14 20:00 UTC (permalink / raw)


Le 14/09/2023 à 17:31, Jeffrey R.Carter a écrit :
> On 2023-09-14 16:02, Blady wrote:
>>
>>       1. with Ada.Containers.Vectors;
>>       2. with Ada.Text_IO;
>>       3. procedure test_20230914_derived_agg is
>>       4.    package My_Float_Lists is new Ada.Containers.Vectors 
>> (Positive, Float);
>>       5.    subtype My_Float_List1 is My_Float_Lists.Vector;
>>       6.    type My_Float_List2 is new My_Float_Lists.Vector with null 
>> record;
>>       7.    ML1 : My_Float_List1 := [-3.1, -6.7, 3.3, -3.14, 0.0];
>>       8.    ML2 : My_Float_List2 := ([-3.1, -6.7, 3.3, -3.14, 0.0] 
>> with null record);
>>                                      |
>>          >>> error: no unique type for this aggregate
> 
> IIUC, you have to qualify the value:
> 
> (My_Float_List1'[-3.1, -6.7, 3.3, -3.14, 0.0] with null record)
> 
> or
> 
> (My_Float_Lists.Vector'[-3.1, -6.7, 3.3, -3.14, 0.0] with null record)
> 
> (not tested)

Thanks Jeff, both proposals are compiled ok by GNAT.

I wonder why the float list aggregate isn't inferred by the compiler and 
need some help with a qualification.

^ permalink raw reply	[relevance 0%]

* Re: Aggregate with derived types.
  2023-09-14 14:02  7% Aggregate with derived types Blady
@ 2023-09-14 15:31  0% ` Jeffrey R.Carter
  2023-09-14 20:00  0%   ` Blady
  0 siblings, 1 reply; 200+ results
From: Jeffrey R.Carter @ 2023-09-14 15:31 UTC (permalink / raw)


On 2023-09-14 16:02, Blady wrote:
> 
>       1. with Ada.Containers.Vectors;
>       2. with Ada.Text_IO;
>       3. procedure test_20230914_derived_agg is
>       4.    package My_Float_Lists is new Ada.Containers.Vectors (Positive, Float);
>       5.    subtype My_Float_List1 is My_Float_Lists.Vector;
>       6.    type My_Float_List2 is new My_Float_Lists.Vector with null record;
>       7.    ML1 : My_Float_List1 := [-3.1, -6.7, 3.3, -3.14, 0.0];
>       8.    ML2 : My_Float_List2 := ([-3.1, -6.7, 3.3, -3.14, 0.0] with null 
> record);
>                                      |
>          >>> error: no unique type for this aggregate

IIUC, you have to qualify the value:

(My_Float_List1'[-3.1, -6.7, 3.3, -3.14, 0.0] with null record)

or

(My_Float_Lists.Vector'[-3.1, -6.7, 3.3, -3.14, 0.0] with null record)

(not tested)

-- 
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

^ permalink raw reply	[relevance 0%]

* Aggregate with derived types.
@ 2023-09-14 14:02  7% Blady
  2023-09-14 15:31  0% ` Jeffrey R.Carter
  0 siblings, 1 reply; 200+ results
From: Blady @ 2023-09-14 14:02 UTC (permalink / raw)


Hello,

I want to extend a container type like Vectors, I've written:
   type My_Float_List2 is new My_Float_Lists.Vector with null record;

But the initialization gives an error line 6:

      1. with Ada.Containers.Vectors;
      2. with Ada.Text_IO;
      3. procedure test_20230914_derived_agg is
      4.    package My_Float_Lists is new Ada.Containers.Vectors 
(Positive, Float);
      5.    subtype My_Float_List1 is My_Float_Lists.Vector;
      6.    type My_Float_List2 is new My_Float_Lists.Vector with null 
record;
      7.    ML1 : My_Float_List1 := [-3.1, -6.7, 3.3, -3.14, 0.0];
      8.    ML2 : My_Float_List2 := ([-3.1, -6.7, 3.3, -3.14, 0.0] with 
null record);
                                     |
         >>> error: no unique type for this aggregate
      9. begin
     10.    Ada.Text_IO.Put_Line (ML1.Element (3)'Image);
     11.    Ada.Text_IO.Put_Line (ML2.Element (3)'Image);
     12. end test_20230914_derived_agg;

The RM says:
4.3.2 Extension Aggregates
1   [An extension_aggregate specifies a value for a type that is a record
extension by specifying a value or subtype for an ancestor of the type,
followed by associations for any components not determined by the
ancestor_part.]
                          Language Design Principles
1.a         The model underlying this syntax is that a record extension can
             also be viewed as a regular record type with an ancestor 
"prefix".
             The record_component_association_list corresponds to 
exactly what
             would be needed if there were no ancestor/prefix type. The
             ancestor_part determines the value of the ancestor/prefix.
                                    Syntax
2       extension_aggregate ::=
             (ancestor_part with record_component_association_list)
3       ancestor_part ::= expression | subtype_mark

It is not so clear for me what could a unique type?
Any clue?

Thanks Pascal.


^ permalink raw reply	[relevance 7%]

* Re: project euler 26
  2023-09-08  7:23  0%                                   ` Dmitry A. Kazakov
@ 2023-09-09  0:25  0%                                     ` Ben Bacarisse
  0 siblings, 0 replies; 200+ results
From: Ben Bacarisse @ 2023-09-09  0:25 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-08 03:32, Ben Bacarisse wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> 
>>> On 2023-09-07 01:32, Ben Bacarisse wrote:
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>>
>>>>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>>>>
>>>> Second, if I try to use a Vector rather than an Ordered_Map, I am told
>>>> that:
>>>> test2.adb:97:05: error: instantiation error at line 12
>>>> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
>>>> It would seem that vector cursors can't be compared using < (at least by
>>>> default).  Maybe the installation needs more arguments.
>>>
>>> Vector has a proper index type. All you have to do is. Given
>>>
>>>     package Integer_Vectors is
>>>        new Ada.Containers.Vectors (Integer, Integer);
>>>
>>> Wrap Element into a function:
>>>
>>>     V : Integer_Vectors.Vector;
>>>     function Element (Index : Integer) return Integer is
>>>     begin
>>>        return V.Element (Index);
>>>     end Element;
>>>     ...
>>>
>>> and use the wrapper.
>> Sure, but the hope was to write something that does not need new
>> code for new situations.  That's what makes it reusable.
>
> Why should it be? You wanted to find maximum of a function. Vector is
> not a function.

I wanted the maximum of a function over a collection (range, array, map,
etc).  In some languages, collections can be scanned so you don't need
to know where the data come from.

>>> Then you would pass Has_Element for it. For integers you would use wrapped
>>> X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid where X is
>>> an object).
>> It's definitely getting what I call cumbersome.
>
> Yes, because you try too hard to make it work where it probably should
> not.

If you think a resuable Ada function that can find the maximum of some F
over some 'collection' X is possible, I'd like to see how it's done.  I
can do it for some kinds of X but I have no idea how general it can be
made in Ada.  I think the answer is either that it can't be very
general, or to make it very general is too much work, or that one should
not be trying in the first place.

(I put 'collection' in quotes because I know that's an Ada term but I
don't necessarily want to restrict the solution to how Ada uses the
term.  For example, I don't think native arrays are collections in the
formal Ada library sense.)

>> I don't think this is incoherent.  The Haskell libraries ensure that any
>> collection that is logically foldable is indeed foldable.
>
> Ada arrays and library containers do not share interfaces.

I was pretty sure that was the case.  Thanks for confirming.  I think
that means there can be no truly generic solution.  But maybe it's
possible at least for all container types in the library?  (But I note
that if you think it /shouldn't/ be done, I won't expect you to show me
how.)

> Should the language allow adding
> ad-hoc interfaces to existing types. Yes, and this is possible in Ada in
> some very uncomfortable AKA cumbersome way, which is why "finding maximum"
> is not a worthy abstraction in Ada.

I suspected one might have to extend the interfaces.  If a simple
abstraction (maximise F over X) does not have a simple representation,
it's not going to be worth it.  Just write a slightly different empty
test and loop each time you need to do it.

>>>> A fix (though it's not really ideal) would be to use function
>>>> composition here (inventing . as the composition operator):
>>>>     Map_Functions.Maximum_At (X.First, X.Last, Period'Access
>>>> . Element'Access)
>>>> but I don't think Ada has a function composition operator, does it?
>>>
>>> No as it would require closures.
>> What closure is required for a function composition?  There is no
>> environment to "close over".
>
> In Ada a function can use anything visible at its declaration point and at
> the location of its body. You can even declare a function inside a
> recursively called function and let it see local variables of each
> recursive call, in effect having an infinite set of functions.

At the point where I want Period.Element I can write the (almost)
one-line function that takes a Cursor and returns Period(Element(C))
entirely mechanically.  Can't the compiler do that?

Note I'm not asking if it /should/ (it may not be "Ada-like" to do
that).  I'm just curious if there really is a technical reason it can't
be done.

>> That's a lot just to use something that is supposed to be reusable.
>
> [rant on]
> An Ada programmer would just write a loop.

Yes, that's fine.  Different languages have different objectives.  Just
write the empty range test and the loop you need for each kind of
collection.  That was definitely the way things were done in the 80s.

>> It only occurred to me after writing the non-generic solution.  I
>> remember Ada as being something of a pioneer in it's attempt to provide
>> generic solutions, so I wondered how far things had come.  I don't think
>> something really widely reusable is possible in this case.
>
> As I said you think in a wrong direction of abstracting the language
> "finding maximum" rather than the problem space, e.g. generalization to
> other bases, other mathematical structures etc.

Generalising to an arbitrary base is local to the function that finds
the answer for one element.  It's an entirely separate axis of
generalisation to that of where the elements come from.

It's interesting to me that you consider one simply wrong and the other
natural.  In some languages the "wrong" one does not even merit
consideration as it's just there for free.  You can concentrate on the
other bases and other structures without worrying if the program will be
able to maximise over the collection in which they are stored.  (For
example, for polynomial residues, they can't come from a range like
2..999.)

I really do appreciate your help.  I would not have got off the ground
with generics without your examples.  Also, one thing I like about
Usenet is coming across people with very different ideas about
programming.  In this case, it seems to be about what is worth
generalising and what isn't.

-- 
Ben.

^ permalink raw reply	[relevance 0%]

* Re: project euler 26
  2023-09-08  1:32  0%                                 ` Ben Bacarisse
@ 2023-09-08  7:23  0%                                   ` Dmitry A. Kazakov
  2023-09-09  0:25  0%                                     ` Ben Bacarisse
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2023-09-08  7:23 UTC (permalink / raw)


On 2023-09-08 03:32, Ben Bacarisse wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On 2023-09-07 01:32, Ben Bacarisse wrote:
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>
>>>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>>>
>>> Second, if I try to use a Vector rather than an Ordered_Map, I am told
>>> that:
>>> test2.adb:97:05: error: instantiation error at line 12
>>> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
>>> It would seem that vector cursors can't be compared using < (at least by
>>> default).  Maybe the installation needs more arguments.
>>
>> Vector has a proper index type. All you have to do is. Given
>>
>>     package Integer_Vectors is
>>        new Ada.Containers.Vectors (Integer, Integer);
>>
>> Wrap Element into a function:
>>
>>     V : Integer_Vectors.Vector;
>>     function Element (Index : Integer) return Integer is
>>     begin
>>        return V.Element (Index);
>>     end Element;
>>     ...
>>
>> and use the wrapper.
> 
> Sure, but the hope was to write something that does not need new
> code for new situations.  That's what makes it reusable.

Why should it be? You wanted to find maximum of a function. Vector is 
not a function. It is in mathematical terms, but not in the language 
terms. The abstraction for finding maximum in a container is just a 
different abstraction.

>> Then you would pass Has_Element for it. For integers you would use wrapped
>> X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid where X is
>> an object).
> 
> It's definitely getting what I call cumbersome.

Yes, because you try too hard to make it work where it probably should not.

> I don't think this is incoherent.  The Haskell libraries ensure that any
> collection that is logically foldable is indeed foldable.

Ada arrays and library containers do not share interfaces. [It is a long 
discussion how they could be]. But similarly, there is no shared 
interface between digits of a number in octal base and a container and a 
string in UTF-16 encoding. Should there be? No. Should the language 
allow adding ad-hoc interfaces to existing types. Yes, and this is 
possible in Ada in some very uncomfortable AKA cumbersome way, which is 
why "finding maximum" is not a worthy abstraction in Ada.

>>> The bottom line is the last argument should be something very general
>>> like the Period function.
>>> A fix (though it's not really ideal) would be to use function
>>> composition here (inventing . as the composition operator):
>>>     Map_Functions.Maximum_At (X.First, X.Last, Period'Access
>>> . Element'Access)
>>> but I don't think Ada has a function composition operator, does it?
>>
>> No as it would require closures.
> 
> What closure is required for a function composition?  There is no
> environment to "close over".

In Ada a function can use anything visible at its declaration point and 
at the location of its body. You can even declare a function inside a 
recursively called function and let it see local variables of each 
recursive call, in effect having an infinite set of functions.

> That's a lot just to use something that is supposed to be reusable.

[rant on]
An Ada programmer would just write a loop. Abstractions are meant to 
abstract the problem domain. If you starting abstract elementary 
programming activities, then there might be something wrong with the 
language or with you.

Then there is a point about readability. When I see a loop I say, aha 
this is what the guy is going to do. When I see a pile of calls of a 
dozen generic instances with arbitrary names, I begin to worry.

In my view it is a road to nowhere, for an imperative language at least. 
The end of this road can be seen in modern C++. 20 years ago C++ was 
severely crippled broken but sometimes enjoyable language. You could 
*read* a C++ program. In these days with all libraries it became Forth 
on steroids. There is no such thing as a C++ program anymore, just calls 
upon calls.
[rant off]

> It only occurred to me after writing the non-generic solution.  I
> remember Ada as being something of a pioneer in it's attempt to provide
> generic solutions, so I wondered how far things had come.  I don't think
> something really widely reusable is possible in this case.

As I said you think in a wrong direction of abstracting the language 
"finding maximum" rather than the problem space, e.g. generalization to 
other bases, other mathematical structures etc.

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

^ permalink raw reply	[relevance 0%]

* Re: project euler 26
  2023-09-07  9:02  4%                               ` Dmitry A. Kazakov
@ 2023-09-08  1:32  0%                                 ` Ben Bacarisse
  2023-09-08  7:23  0%                                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Ben Bacarisse @ 2023-09-08  1:32 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-07 01:32, Ben Bacarisse wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> 
>>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>>
>>>> I am curious to know how reusable this is.  Can the packages be
>>>> instantiated in such a way that the argument ranges over the elements
>>>> of, say, and Ordered_Map?
>>>
>>> Sure:
>>>
>>>     with Ada.Containers.Ordered_Maps;
>>>
>>>     package Integer_Maps is
>>>        new Ada.Containers.Ordered_Maps (Integer, Integer);
>>>     use Integer_Maps;
>>>     package Cursor_Arguments is new Generic_Arguments (Cursor);
>> Ah!  So the arguments correspond to the "with" functions in the order
>> listed, and, since Cursor already has Next, there no need to specify
>> anything.
>
> Yes, because the formal argument is
>
>    with function Next (Value : Argument_Type)
>       return Argument_Type is <>;
>
> If it were
>
>    with function Next (Value : Argument_Type)
>       return Argument_Type;
>
> You would have to specify the actual. The part "is <>" tells to match a
> visible function Next.

Thanks.  I remember that now.  Given Ada's preference for words, it's a
mysterious choice.

>> There are a couple of details that prevent your Maximum_At function from
>> working properly in this case though.  First, we can't have an empty
>> map, because X.Last can't be compared with X.First when either is
>> No_Element, so the test for Right < Left fails before the desired error
>> can be raised.
>
> Yes, cursors is bad idea, in the end they all are pointers. No_Element is
> an equivalent of null which shows.
>
> However Maximum_At will propagate Constraint_Error if either of the bounds
> is No_Element. So the implementation would work.

Sure, but ideally we want the error we decided on for this situation.
Since the intent is to be generic, it's a shame to get one error with
some instantiations and a different one with others.

>> Second, if I try to use a Vector rather than an Ordered_Map, I am told
>> that:
>> test2.adb:97:05: error: instantiation error at line 12
>> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
>> It would seem that vector cursors can't be compared using < (at least by
>> default).  Maybe the installation needs more arguments.
>
> Vector has a proper index type. All you have to do is. Given
>
>    package Integer_Vectors is
>       new Ada.Containers.Vectors (Integer, Integer);
>
> Wrap Element into a function:
>
>    V : Integer_Vectors.Vector;
>    function Element (Index : Integer) return Integer is
>    begin
>       return V.Element (Index);
>    end Element;
>    ...
>
> and use the wrapper.

Sure, but the hope was to write something that does not need new
code for new situations.  That's what makes it reusable.

>> Anyway, I am still not sure how to write a generic test for an empty
>> range.
>
> The problem is that the implementation of Cursor that breaks
> abstraction. The abstraction of an argument does not permit ideal
> non-values. Cursors and pointers have non-values. So if you want to test
> for non-values ahead, instead of surprising the function, you need to add a
> test for value validity to the abstraction:
>
> generic
>    -- Ordered argument
>    type Argument_Type is private;
>    with function Valid (Value : Argument_Type) return Boolean is <>;
>    ...
> package Generic_Arguments is
>
> Then you would pass Has_Element for it. For integers you would use wrapped
> X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid where X is
> an object).

It's definitely getting what I call cumbersome.

>> It's possible I was not clear about what I was aiming for.  I was hoping
>> to be able to find the maximum of some arbitrary function, taking the
>> function's arguments from any sequential collection.
>
> That is a different abstraction. You need a generic collection instead of
> generic ordered values. E.g.
>
> generic
>    with package Arguments is new Ada.Containers.Ordered_Sets (<>);
>    with package Values is new Generic_Values (<>);
> package Generic_Comparable_Valued is
>    use Arguments, Values;
>    function Maximum_At
>             (  Domain : Set;
>                Func : access function (Argument : Element_Type)
>                       return Value_Type
>             )  return Value_Type;
>    -- Other useless functions
> end Generic_Comparable_Valued;
>
> package body Generic_Comparable_Valued is
>    function Maximum_At
>             (  Domain : Set;
>                Func : access function (Argument : Element_Type)
>                       return Value_Type
>             )  return Value_Type is
>       Max      : Value_Type;
>       Value    : Value_Type;
>       Position : Cursor;
>    begin
>       if Domain.Is_Empty then
>          raise Constraint_Error with "Empty set";
>       end if;
>       Position := Domain.First;
>       Max := Func (Element (Position));
>       while Position /= Domain.Last loop
>          Position := Next (Position);
>          Value := Func (Element (Position));
>          if Max < Value then
>             Max := Value;
>          end if;
>       end loop;
>       return Max;
>    end Maximum_At;
> end Generic_Comparable_Valued;
>
>> Either a simple
>> range of values, an array or vector of values, a list of values or even
>> an ordered map of values -- any ordered list of values.
>
> In practice such abstraction have too much physical and mental
> overhead. E.g. large sets of values implemented differently from
> Ada.Containers.Ordered_Sets depending on the operations required. For
> example, let you need a set complement? Usually programmers simply stick
> with software patterns instead. Too much reliance of libraries make
> programs incoherent.

The core of my Haskell solution is just a function decimalRepeatLength
that returns the repeat length given a divisor.  But once I'd got the
answer (by applying it to 2 to 999 and getting the maximum) I wondered
what would happen if the numbers were not in a simple range.  Is it easy
to write a `maximisedOver` function that finds the maximum of some
function over any ordered collection (technically, a "foldable" type in
Haskell).

Well, yes, it is easy:

  function `maximisedOver` anything = maximum (fmap function anything)

so the solution to the project Euler problem is just

  decimalRepeatLength `maximisedOver` [2..999]

but I can also find the maximum of this (or any other suitable) function
over an array, a hash map, a vector... whatever.  No code changes
anywhere.  It even works with arrays of any number of dimensions
regardless of the index bounds.

maximisedOver is genuinely generic and reusable.

I don't think this is incoherent.  The Haskell libraries ensure that any
collection that is logically foldable is indeed foldable.

>> The bottom line is the last argument should be something very general
>> like the Period function.
>> A fix (though it's not really ideal) would be to use function
>> composition here (inventing . as the composition operator):
>>    Map_Functions.Maximum_At (X.First, X.Last, Period'Access
>> . Element'Access)
>> but I don't think Ada has a function composition operator, does it?
>
> No as it would require closures.

What closure is required for a function composition?  There is no
environment to "close over".

> So you can have a generic composition
> operator, no problem, but not a first-class one. However you can simply add
> Maximum_At with four arguments to the package.

This may be the closest we can get with Ada.

>> Another solution would be to write Maximum_At so that it knows it has a
>> cursor argument, but then I don't think it would work for native arrays,
>> would it?  And we'd loose plain ranges altogether.
>
> You can write a generic package creating array cursors:
>
> generic
>    type Index_Type is (<>);
>    type Element_Type is private;
>    type Array_Type is array (Index_Type range <>) of Element_Type;
> package Array_Cursors is
>    type Cursor is private;
>    function First (Container : Array_Type) return Cursor;
>    function Element (Position : Cursor) return Element_Type;
>    function "<" (Left, Right : Cursor) return Boolean;
>    ...
> private
>    package Dirty_Tricks is
>       new System.Address_To_Access_Conversions (Array_Type);
>    use Dirty_Tricks;
>    type Cursor is record
>       Domain : Object_Pointer;
>       Index  : Index_Type;
>    end record;
> end Array_Cursors;
>
> package body Array_Cursors is
>    function "<" (Left, Right : Cursor) return Boolean is
>    begin
>       if Left.Domain = null or else Left.Domain /= Right.Domain then
>          raise Constraint_Error with "Incomparable cursors";
>       end if;
>       return Left.Index < Right.Index;
>    end "<";
>
>    function Element (Position : Cursor) return Element_Type is
>    begin
>       if Position.Domain = null or else
>          Position.Index not in Position.Domain'Range
>       then
>          raise Constraint_Error with "Invalid cursor";
>       else
>          return Position.Domain (Position.Index);
>       end if;
>    end Element;
>
>    function First (Container : Array_Type) return Cursor is
>    begin
>       if Container'Length = 0 then
>          raise Constraint_Error with "Empty array";
>       else
>          return (To_Pointer (Container'Address), Container'First);
>       end if;
>    end First;
>
> end Array_Cursors;

That's a lot just to use something that is supposed to be reusable.

>> You seem to be on your own as far as helping out is concerned!
>
> Because it started as a numeric puzzle. You should have asked directly
> about generics or tagged types instead.

It only occurred to me after writing the non-generic solution.  I
remember Ada as being something of a pioneer in it's attempt to provide
generic solutions, so I wondered how far things had come.  I don't think
something really widely reusable is possible in this case.

-- 
Ben.

^ permalink raw reply	[relevance 0%]

* Re: project euler 26
  @ 2023-09-07  9:02  4%                               ` Dmitry A. Kazakov
  2023-09-08  1:32  0%                                 ` Ben Bacarisse
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2023-09-07  9:02 UTC (permalink / raw)


On 2023-09-07 01:32, Ben Bacarisse wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>
>>> I am curious to know how reusable this is.  Can the packages be
>>> instantiated in such a way that the argument ranges over the elements
>>> of, say, and Ordered_Map?
>>
>> Sure:
>>
>>     with Ada.Containers.Ordered_Maps;
>>
>>     package Integer_Maps is
>>        new Ada.Containers.Ordered_Maps (Integer, Integer);
>>     use Integer_Maps;
>>     package Cursor_Arguments is new Generic_Arguments (Cursor);
> 
> Ah!  So the arguments correspond to the "with" functions in the order
> listed, and, since Cursor already has Next, there no need to specify
> anything.

Yes, because the formal argument is

    with function Next (Value : Argument_Type)
       return Argument_Type is <>;

If it were

    with function Next (Value : Argument_Type)
       return Argument_Type;

You would have to specify the actual. The part "is <>" tells to match a 
visible function Next.

> There are a couple of details that prevent your Maximum_At function from
> working properly in this case though.  First, we can't have an empty
> map, because X.Last can't be compared with X.First when either is
> No_Element, so the test for Right < Left fails before the desired error
> can be raised.

Yes, cursors is bad idea, in the end they all are pointers. No_Element 
is an equivalent of null which shows.

However Maximum_At will propagate Constraint_Error if either of the 
bounds is No_Element. So the implementation would work.

> Second, if I try to use a Vector rather than an Ordered_Map, I am told
> that:
> 
> test2.adb:97:05: error: instantiation error at line 12
> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
> 
> It would seem that vector cursors can't be compared using < (at least by
> default).  Maybe the installation needs more arguments.

Vector has a proper index type. All you have to do is. Given

    package Integer_Vectors is
       new Ada.Containers.Vectors (Integer, Integer);

Wrap Element into a function:

    V : Integer_Vectors.Vector;
    function Element (Index : Integer) return Integer is
    begin
       return V.Element (Index);
    end Element;
    ...

and use the wrapper.

> Anyway, I am still not sure how to write a generic test for an empty
> range.

The problem is that the implementation of Cursor that breaks 
abstraction. The abstraction of an argument does not permit ideal 
non-values. Cursors and pointers have non-values. So if you want to test 
for non-values ahead, instead of surprising the function, you need to 
add a test for value validity to the abstraction:

generic
    -- Ordered argument
    type Argument_Type is private;
    with function Valid (Value : Argument_Type) return Boolean is <>;
    ...
package Generic_Arguments is

Then you would pass Has_Element for it. For integers you would use 
wrapped X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid 
where X is an object).

> It's possible I was not clear about what I was aiming for.  I was hoping
> to be able to find the maximum of some arbitrary function, taking the
> function's arguments from any sequential collection.

That is a different abstraction. You need a generic collection instead 
of generic ordered values. E.g.

generic
    with package Arguments is new Ada.Containers.Ordered_Sets (<>);
    with package Values is new Generic_Values (<>);
package Generic_Comparable_Valued is
    use Arguments, Values;
    function Maximum_At
             (  Domain : Set;
                Func : access function (Argument : Element_Type)
                       return Value_Type
             )  return Value_Type;
    -- Other useless functions
end Generic_Comparable_Valued;

package body Generic_Comparable_Valued is
    function Maximum_At
             (  Domain : Set;
                Func : access function (Argument : Element_Type)
                       return Value_Type
             )  return Value_Type is
       Max      : Value_Type;
       Value    : Value_Type;
       Position : Cursor;
    begin
       if Domain.Is_Empty then
          raise Constraint_Error with "Empty set";
       end if;
       Position := Domain.First;
       Max := Func (Element (Position));
       while Position /= Domain.Last loop
          Position := Next (Position);
          Value := Func (Element (Position));
          if Max < Value then
             Max := Value;
          end if;
       end loop;
       return Max;
    end Maximum_At;
end Generic_Comparable_Valued;

> Either a simple
> range of values, an array or vector of values, a list of values or even
> an ordered map of values -- any ordered list of values.

In practice such abstraction have too much physical and mental overhead. 
E.g. large sets of values implemented differently from 
Ada.Containers.Ordered_Sets depending on the operations required. For 
example, let you need a set complement? Usually programmers simply stick 
with software patterns instead. Too much reliance of libraries make 
programs incoherent.

> The bottom line is the last argument should be something very general
> like the Period function.
> 
> A fix (though it's not really ideal) would be to use function
> composition here (inventing . as the composition operator):
> 
>    Map_Functions.Maximum_At (X.First, X.Last, Period'Access . Element'Access)
> 
> but I don't think Ada has a function composition operator, does it?

No as it would require closures. So you can have a generic composition 
operator, no problem, but not a first-class one. However you can simply 
add Maximum_At with four arguments to the package.

> Another solution would be to write Maximum_At so that it knows it has a
> cursor argument, but then I don't think it would work for native arrays,
> would it?  And we'd loose plain ranges altogether.

You can write a generic package creating array cursors:

generic
    type Index_Type is (<>);
    type Element_Type is private;
    type Array_Type is array (Index_Type range <>) of Element_Type;
package Array_Cursors is
    type Cursor is private;
    function First (Container : Array_Type) return Cursor;
    function Element (Position : Cursor) return Element_Type;
    function "<" (Left, Right : Cursor) return Boolean;
    ...
private
    package Dirty_Tricks is
       new System.Address_To_Access_Conversions (Array_Type);
    use Dirty_Tricks;
    type Cursor is record
       Domain : Object_Pointer;
       Index  : Index_Type;
    end record;
end Array_Cursors;

package body Array_Cursors is
    function "<" (Left, Right : Cursor) return Boolean is
    begin
       if Left.Domain = null or else Left.Domain /= Right.Domain then
          raise Constraint_Error with "Incomparable cursors";
       end if;
       return Left.Index < Right.Index;
    end "<";

    function Element (Position : Cursor) return Element_Type is
    begin
       if Position.Domain = null or else
          Position.Index not in Position.Domain'Range
       then
          raise Constraint_Error with "Invalid cursor";
       else
          return Position.Domain (Position.Index);
       end if;
    end Element;

    function First (Container : Array_Type) return Cursor is
    begin
       if Container'Length = 0 then
          raise Constraint_Error with "Empty array";
       else
          return (To_Pointer (Container'Address), Container'First);
       end if;
    end First;

end Array_Cursors;

> But then (I think) the only function one could pass would be something
> like Element as in you example above.  Using an ordered set of integers
> would not allow
> 
>    Map_Functions.Maximum_At (Set.First, Set.Last, Period'Access)
> 
> would it?

Ordered_Set cursors are ordered like Ordered_Map ones, so it should work.

>>> I am asking you but I am also the group.  I appreciate your help,
>>> but don't want you to feel any obligation to keep helping!
>>
>> No problem.
> 
> You seem to be on your own as far as helping out is concerned!

Because it started as a numeric puzzle. You should have asked directly 
about generics or tagged types instead.

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

^ permalink raw reply	[relevance 4%]

* Re: Formal Package Compiler Differences
  2023-07-14 19:17  8% Formal Package Compiler Differences Jeffrey R.Carter
@ 2023-07-14 19:27  0% ` Jeffrey R.Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R.Carter @ 2023-07-14 19:27 UTC (permalink / raw)


On 2023-07-14 21:17, Jeffrey R.Carter wrote:
> I have a generic pkg;
> 
> with Ada.Containers.Vectors;
> 
> generic -- Vector_Conversions
>     type Index is range <>;
>     type Element is private;
>     type Fixed is array (Index range <>) of Element;
> 
>     with function "=" (Left : in Element; Right : in Element) return Boolean
>     is <>;

Oops! This "=" should be removed to get the behavior described.

> 
>     with package Unbounded is new Ada.Containers.Vectors
>        (Index_Type => Index, Element_Type => Element);
> package Vector_Conversions is
>     -- Empty
> end Vector_Conversions;
> 
> and an instantiation of
> 
> with Ada.Containers.Vectors;
> with Ada.Strings.Unbounded;
> with Vector_Conversions;
> 
> procedure Instance_Test is
>     use Ada.Strings.Unbounded;
> 
>     package String_Lists is new Ada.Containers.Vectors
>        (Index_Type => Positive, Element_Type => Unbounded_String);
> 
>     type String_List is array (Positive range <>) of Unbounded_String;
> 
>     package Conversions is new Vector_Conversions
>        (Index     => Positive,
>         Element   => Unbounded_String,
>         Fixed     => String_List,
>         Unbounded => String_Lists);
> begin -- Instance_Test
>     null;
> end Instance_Test;
> 
> Compiler G compiles this and it works fine.
> 
> Compiler O fails to compile the instantiation with the error msg "The subprogram 
> actuals for the formal package and actual package must statically denote the 
> same entity", pointing to the Unbounded parameter association and referencing 
> ARM 12.7(8). If I add an explicit "=" with "is <>" to Vector_Conversions, then 
> compiler O compiles it and it works fine.
> 
> Possibly one of the compilers has an error, but possibly they're both correct, 
> and I'm wondering if it's possible to tell which is the case.
> 
> (If anyone is interested, the actual generic pkg where I encountered this is 
> PragmARC.Conversions.Vectors from the PragmAda Reusable Components 
> [https://github.com/jrcarter/PragmARC]), and I will supply the actual code that 
> instantiates it on demand. What I've presented is a first attempt at a minimal 
> reproducer.)
> 

-- 
Jeff Carter
"Make sure your code 'does nothing' gracefully."
Elements of Programming Style
196

^ permalink raw reply	[relevance 0%]

* Formal Package Compiler Differences
@ 2023-07-14 19:17  8% Jeffrey R.Carter
  2023-07-14 19:27  0% ` Jeffrey R.Carter
  0 siblings, 1 reply; 200+ results
From: Jeffrey R.Carter @ 2023-07-14 19:17 UTC (permalink / raw)


I have a generic pkg;

with Ada.Containers.Vectors;

generic -- Vector_Conversions
    type Index is range <>;
    type Element is private;
    type Fixed is array (Index range <>) of Element;

    with function "=" (Left : in Element; Right : in Element) return Boolean
    is <>;

    with package Unbounded is new Ada.Containers.Vectors
       (Index_Type => Index, Element_Type => Element);
package Vector_Conversions is
    -- Empty
end Vector_Conversions;

and an instantiation of

with Ada.Containers.Vectors;
with Ada.Strings.Unbounded;
with Vector_Conversions;

procedure Instance_Test is
    use Ada.Strings.Unbounded;

    package String_Lists is new Ada.Containers.Vectors
       (Index_Type => Positive, Element_Type => Unbounded_String);

    type String_List is array (Positive range <>) of Unbounded_String;

    package Conversions is new Vector_Conversions
       (Index     => Positive,
        Element   => Unbounded_String,
        Fixed     => String_List,
        Unbounded => String_Lists);
begin -- Instance_Test
    null;
end Instance_Test;

Compiler G compiles this and it works fine.

Compiler O fails to compile the instantiation with the error msg "The subprogram 
actuals for the formal package and actual package must statically denote the 
same entity", pointing to the Unbounded parameter association and referencing 
ARM 12.7(8). If I add an explicit "=" with "is <>" to Vector_Conversions, then 
compiler O compiles it and it works fine.

Possibly one of the compilers has an error, but possibly they're both correct, 
and I'm wondering if it's possible to tell which is the case.

(If anyone is interested, the actual generic pkg where I encountered this is 
PragmARC.Conversions.Vectors from the PragmAda Reusable Components 
[https://github.com/jrcarter/PragmARC]), and I will supply the actual code that 
instantiates it on demand. What I've presented is a first attempt at a minimal 
reproducer.)

-- 
Jeff Carter
"Make sure your code 'does nothing' gracefully."
Elements of Programming Style
196

^ permalink raw reply	[relevance 8%]

* Re: Hi guys! I've been inactive for a long time but now started to develop a hobby application. I found a strange behaviour with gdb. Locally renaming a function S in order to shorten the source code visits cygwin.S during execution. thie is very awk
  @ 2023-04-18 11:18  4%       ` Petter
  0 siblings, 0 replies; 200+ results
From: Petter @ 2023-04-18 11:18 UTC (permalink / raw)


Thanks for the advice. But I could not find an easy way to start using another newsreader. Also, since I'm now retired. I'm not prepared to spend any more money. 

I'd be grateful if someone addressed to problem in the OP: why do i have to hit F7 so many times? I also found out that I might not want to step into Ada.Containers.Vectors which is visited a lot of times for just a simple "for I of Vector". And more, something periodically triggers an abort_signal caught by ACV causing more F7s.

(I semi-retired 2 years ago and fully last year from a career in consultancy. Some of you have seen my posts a few years ago, when I was at in order Nobel Tech, SAAB Ericsson Aerotronics, SAAB Dynamics. Randy might remember that I started my career at SAAB UNIVAC later to become UNISYS which Randy and friends created an ADA Compiler which I sadly never had a chance to try.)

^ permalink raw reply	[relevance 4%]

* Is this a compiler bug ?
@ 2023-03-19  6:17  6% Rod Kay
  0 siblings, 0 replies; 200+ results
From: Rod Kay @ 2023-03-19  6:17 UTC (permalink / raw)


Hi all,

    Came across this during a port of the Box2D physics engine.

    It's a generic Stack package using 'ada.Containers.Vectors' to 
implement the stack.

    One generic parameter is the 'initial_Capacity' of the stack, used 
in the 'to_Stack' construction function, via the Vectors 
'reserve_Capacity' procedure.

    In the 'to_Stack' function, the Capacity is reserved correctly but 
in the test program when the stack is created and assigned to a 
variable, the capacity is 0.

    Here is the (very small) source code ...

    https://gist.github.com/charlie5/7b4d863227a510f834c2bfd781dd50ba


    The output I get with GCC 12.2.0 is ...

[rod@orth bug]$ ./stack_bug
to_Stack ~ Initial Capacity: 256
to_Stack ~ Before reserve:   0
to_Stack ~ After reserve:    256
stack_Bug ~ Actual Capacity: 0


Regards.

^ permalink raw reply	[relevance 6%]

* Re: Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ?
  2023-02-14  8:49 14% Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ? reinert
  2023-02-14  9:35  8% ` Jeffrey R.Carter
  2023-03-15 10:05  8% ` Marius Amado-Alves
@ 2023-03-15 14:24  8% ` Brad Moore
  2 siblings, 0 replies; 200+ results
From: Brad Moore @ 2023-03-15 14:24 UTC (permalink / raw)


On Tuesday, February 14, 2023 at 1:49:55 AM UTC-7, reinert wrote:
> Hello, 
> , 
> Sometimes, I have to sort records. One possibility is to use Generig_Sorting under Ada.Containers.Vectors and eksplicitly use Sort. An alternative is to use Ada.Containders.Ordered_Sets and somehow get sorting "for free". 
> 
> I would like to get arguments for and against these two alternatives. 
> 
> reinert

I might use the generic sorting for example, for the case where the data is more static and needs to be sorted once, whereas I'd use an ordered set if the data is continuously being updated and manipulated, or if I needed set semantics.

Brad

^ permalink raw reply	[relevance 8%]

* Re: Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ?
  2023-02-14  8:49 14% Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ? reinert
  2023-02-14  9:35  8% ` Jeffrey R.Carter
@ 2023-03-15 10:05  8% ` Marius Amado-Alves
  2023-03-15 14:24  8% ` Brad Moore
  2 siblings, 0 replies; 200+ results
From: Marius Amado-Alves @ 2023-03-15 10:05 UTC (permalink / raw)


> Sometimes, I have to sort records. One possibility is to use Generig_Sorting under Ada.Containers.Vectors and eksplicitly use Sort. An alternative is to use Ada.Containders.Ordered_Sets and somehow get sorting "for free". 
> 
> I would like to get arguments for and against these two alternatives. 
> 
> reinert

Sets have slightly stricter semantics, namely no duplicates. Normally, if the real data has this semantics, you should use sets (and populate with Include or else catch the exception raised upon trying to Insert a duplicate).

^ permalink raw reply	[relevance 8%]

* Re: Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ?
  2023-02-14 10:46  8%   ` reinert
@ 2023-02-14 18:48  8%     ` G.B.
  0 siblings, 0 replies; 200+ results
From: G.B. @ 2023-02-14 18:48 UTC (permalink / raw)


On 14.02.23 11:46, reinert wrote:
> My main argument for using Ordered_Sets is that it seems to be less verbose and somehow garanteres sorting. Myset.Last/First always provides the "largest"/"smallest" element.

You could measure performance of operations
that you find critical, given a typical number
of elements in the set. If there isn't any operation
that is particularly critical, some weighted
average of all set operations might be of interest.

Two similar data structures might both use a common
algorithm, such as sorting. If a program uses both
data structures, then having just one algorithm
might be advantageous, if only for the size of
the executable.

^ permalink raw reply	[relevance 8%]

* Re: Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ?
  2023-02-14  9:35  8% ` Jeffrey R.Carter
@ 2023-02-14 10:46  8%   ` reinert
  2023-02-14 18:48  8%     ` G.B.
  0 siblings, 1 reply; 200+ results
From: reinert @ 2023-02-14 10:46 UTC (permalink / raw)


My main argument for using Ordered_Sets is that it seems to be less verbose and somehow garanteres sorting. Myset.Last/First always provides the "largest"/"smallest" element.

reinert



^ permalink raw reply	[relevance 8%]

* Re: Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ?
  2023-02-14  8:49 14% Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ? reinert
@ 2023-02-14  9:35  8% ` Jeffrey R.Carter
  2023-02-14 10:46  8%   ` reinert
  2023-03-15 10:05  8% ` Marius Amado-Alves
  2023-03-15 14:24  8% ` Brad Moore
  2 siblings, 1 reply; 200+ results
From: Jeffrey R.Carter @ 2023-02-14  9:35 UTC (permalink / raw)


On 2023-02-14 09:49, reinert wrote:
> 
> Sometimes, I have to sort records. One possibility is to use Generig_Sorting under Ada.Containers.Vectors and eksplicitly use Sort.  An alternative is to use Ada.Containders.Ordered_Sets and somehow get sorting "for free".
> 
> I would like to get arguments for and against these two alternatives.

Both should be O(NlogN), so the distinction is which works better for what you 
do with them after they are sorted.

-- 
Jeff Carter
"[B]ecause of our experience in security, we are convinced
that C is too error-prone. Its loose typing, its unsafe
bitfields management, too many compiler dependent behaviors,
etc. easily lead to vulnerabilities."
EwoK developers
163

^ permalink raw reply	[relevance 8%]

* Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ?
@ 2023-02-14  8:49 14% reinert
  2023-02-14  9:35  8% ` Jeffrey R.Carter
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: reinert @ 2023-02-14  8:49 UTC (permalink / raw)


Hello,

Sometimes, I have to sort records. One possibility is to use Generig_Sorting under Ada.Containers.Vectors and eksplicitly use Sort.  An alternative is to use Ada.Containders.Ordered_Sets and somehow get sorting "for free". 

I would like to get arguments for and against these two alternatives.

reinert

^ permalink raw reply	[relevance 14%]

* Re: Real_Arrays on heap with overloaded operators and clean syntax
  @ 2023-01-24 19:47  5% ` Gautier write-only address
  0 siblings, 0 replies; 200+ results
From: Gautier write-only address @ 2023-01-24 19:47 UTC (permalink / raw)


There are plenty of legitimate complaints and good ideas in this thread.

- need for a package for large matrices (issue with stack allocation)
- should support approximations (at least, floating-point) real and complex numbers (and perhaps others)
- should support various matrix storages: sparse storages, band storages, ...

Fortunately Ada (not "ADA" = "American Dentist Association" and some others...) is powerful enough to have such components written in Ada itself (with GNAT, it is done exactly like this).
So _we_ don't need to wait that _they_ do anything about it :-)

So, if I summarize the ideas discussed and combine with stuff grabbed from a toolbox of mine ( https://github.com/zertovitch/mathpaqs
 ), I obtain the following specification.
The choice between different kind of matrix storages would be trivial.
Comments are welcome!

---8<--------8<--------8<--------8<--------8<--------8<-----
--  Draft of a specification for an universal matrix package.

--  The elements of the vectors and matrices can be of any algebraic ring
--  and their implementation, eventually approximate:
--
--    - integers (stored as Integer, Integer_n or Big_Integer)
--    - modular integers
--    - real numbers (approximated as floating-point, fixed-point or Big_Real)
--    - complex numbers
--    - rational numbers
--    - polynomials (of real, complex, rational, ...)
--    - other matrices
--    - ...

with Ada.Containers.Vectors;

generic

  type Ring_Element is private;  --  Element of an algebraic ring

  zero, one : Ring_Element;                                     --  0 and 1 elements

  with function "-" (a : Ring_Element) return Ring_Element;     --  Unary operators

  with function "+" (a, b : Ring_Element) return Ring_Element;  --  Binary operators
  with function "-" (a, b : Ring_Element) return Ring_Element;
  with function "*" (a, b : Ring_Element) return Ring_Element;

package Universal_Matrices is

  package UM_Vectors is new Ada.Containers.Vectors (Positive, Ring_Element);

  subtype Vector is UM_Vectors.Vector;

  -------------------------
  --  Vector operations  --
  -------------------------

  function "*" (v : Vector; factor : Ring_Element) return Vector;
  function "*" (factor : Ring_Element; v : Vector) return Vector;

  --  v := factor * v :
  procedure Scale_Left (v : in out Vector; factor : Ring_Element);

  function "-" (v : Vector) return Vector;

  function "+" (v, w : Vector) return Vector;
  --  v := v + w :
  procedure Add (v : in out Vector; w : Vector);
  --  v := v + factor * w :
  procedure Add_Left_Scaled (v : in out Vector; factor : Ring_Element; w : Vector);

  function "-" (v, w : Vector) return Vector;
  --  v := v - w :
  procedure Subtract (v : in out Vector; w : Vector);

  function "*" (v, w : Vector) return Ring_Element;

  --  Euclidean norm and distance:
  function Square_L2_Norm (v : Vector) return Ring_Element;
  function Square_L2_Distance (v, w : Vector) return Ring_Element;

  -------------------------------------------------------------------
  --  Root matrix type.                                            --
  --  Possible derivations: dense, sparse, band storage matrices.  --
  -------------------------------------------------------------------

  type Matrix is interface;

  -------------------------
  --  Matrix operations  --
  -------------------------

  function Transpose (A : Matrix) return Matrix is abstract;
  function Identity (order : Positive) return Matrix is abstract;
  function "*" (factor : Ring_Element; A : Matrix) return Matrix is abstract;
  function "*" (A : Matrix; factor : Ring_Element) return Matrix is abstract;
  function "*" (A, B : Matrix) return Matrix is abstract;
  function "+" (A, B : Matrix) return Matrix is abstract;
  function "-" (A, B : Matrix) return Matrix is abstract;

  --  Matrix-Vector operations

  function "*" (A : Matrix; x : Vector) return Vector is abstract;

end Universal_Matrices;

^ permalink raw reply	[relevance 5%]

* Re: Compiler error (2) ?
  2022-09-26  8:47  7%   ` reinert
@ 2022-09-26  9:59  0%     ` reinert
  0 siblings, 0 replies; 200+ results
From: reinert @ 2022-09-26  9:59 UTC (permalink / raw)


Sorry for some typos in my latest post, but the intelligent reader should understand :-)

reinert

mandag 26. september 2022 kl. 10:47:16 UTC+2 skrev reinert:
> This is what I (also) get: 
> 
> test1a.adb:16:42: error: expected type "Standard.Integer" 
> test1a.adb:16:42: error: found type "Ada.Containers.Count_Type" 
> 
> compilation of test1a.adb failed 
> 
> gprbuild: *** compilation phase failed 
> error: Command ["gprbuild", "-s", "-j0", "-p", "-P", "/home/reinert/test1a/test1a.gpr"] exited with code 4 
> error: Compilation failed. 
> --------------------------------------------------------------------------------------------------- 
> **However, the following version goes through the compiler and runs 
> (using "subtype n_t is Positive range 3..Positive'Last;" for)
> in the package specification) - confirming what Simon says: 
> 
> with Ada.Text_IO; 
> with Ada.Containers.Vectors; 
> procedure test1a is 
> type s_name_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9); 
> for s_name_type use 
> (S0 => 0, S1 => 1, S2 => 2, S3 => 3, S4 => 4, 
> S5 => 5, S6 => 6, S7 => 7, S8 => 8, S9 => 9);
> subtype n_t is Positive range 3..Positive'Last;
> package s_names_p is new Ada.Containers.Vectors
> (Index_Type => n_t, Element_Type => s_name_type); 
> k : integer := 7;
> n : constant integer := 7;
> -- n : constant integer := k; -- uncomment this line and comment out the line above.
> s_names: constant s_names_p.Vector := [for i in 3..n => S0]; 
> begin 
> Ada.Text_IO.Put_Line(s_names'Image); 
> end test1a;
> reinert
> mandag 26. september 2022 kl. 10:34:18 UTC+2 skrev J-P. Rosen: 
> > Please give the exact error message, and why you think it could be a 
> > compiler error. Otherwise, it's hard to help... 
> > Le 26/09/2022 à 08:54, reinert a écrit : 
> > > Hello, 
> > > 
> > > This must reveal a compiler error : 
> > > ------------------------------------------------------------------------------------------------------- 
> > > with Ada.Text_IO; 
> > > with Ada.Containers.Vectors; 
> > > procedure test1a is 
> > > type s_name_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9); 
> > > for s_name_type use 
> > > (S0 => 0, S1 => 1, S2 => 2, S3 => 3, S4 => 4, 
> > > S5 => 5, S6 => 6, S7 => 7, S8 => 8, S9 => 9); 
> > > package s_names_p is new Ada.Containers.Vectors 
> > > (Index_Type => Positive, Element_Type => s_name_type); 
> > > k : integer := 7; 
> > > 
> > > -- n : constant integer := 7; -- uncomment this line and comment out the line below. 
> > > n : constant integer := k; 
> > > 
> > > s_names: constant s_names_p.Vector := [for i in 3..n => S0]; 
> > > begin 
> > > Ada.Text_IO.Put_Line(s_names'Image); 
> > > end test1a; 
> > > ------------------------------------------------------------------------------------------------------- 
> > > (compiled using alire and 
> > > package Compiler is 
> > > for Switches ("ada") use ("-gnatwa", "-gnata", "-gnatX", "-gnatwv"); 
> > > end Compiler; 
> > > ------------------------------------------------------------------------------------------------------- 
> > > 
> > > Right? 
> > > 
> > > reinert 
> > -- 
> > J-P. Rosen 
> > Adalog 
> > 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX 
> > Tel: +33 1 45 29 21 52 
> > https://www.adalog.fr

^ permalink raw reply	[relevance 0%]

* Re: Compiler error (2) ?
  2022-09-26  8:34  0% ` J-P. Rosen
@ 2022-09-26  8:47  7%   ` reinert
  2022-09-26  9:59  0%     ` reinert
  0 siblings, 1 reply; 200+ results
From: reinert @ 2022-09-26  8:47 UTC (permalink / raw)


This is what I (also) get:

test1a.adb:16:42: error: expected type "Standard.Integer"
test1a.adb:16:42: error: found type "Ada.Containers.Count_Type"

   compilation of test1a.adb failed

gprbuild: *** compilation phase failed
error: Command ["gprbuild", "-s", "-j0", "-p", "-P", "/home/reinert/test1a/test1a.gpr"] exited with code 4
error: Compilation failed.
---------------------------------------------------------------------------------------------------
**However, the following version goes through the compiler and runs 
(using "subtype n_t is Positive range 3..Positive'Last;" for)
in the package specification) - confirming what Simon says:

with Ada.Text_IO;
with Ada.Containers.Vectors;
procedure test1a is
   type s_name_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
   for s_name_type use
      (S0 => 0, S1 => 1, S2 => 2, S3 => 3, S4 => 4,
       S5 => 5, S6 => 6, S7 => 7, S8 => 8, S9 => 9);
   subtype n_t is Positive range 3..Positive'Last;
   package s_names_p is new Ada.Containers.Vectors
     (Index_Type => n_t, Element_Type => s_name_type);
   k : integer := 7;

   n : constant integer := 7; 
 --  n : constant integer := k; -- uncomment this line and comment out the line above.

   s_names: constant s_names_p.Vector := [for i in 3..n => S0];
begin
   Ada.Text_IO.Put_Line(s_names'Image);
end test1a;


reinert




mandag 26. september 2022 kl. 10:34:18 UTC+2 skrev J-P. Rosen:
> Please give the exact error message, and why you think it could be a 
> compiler error. Otherwise, it's hard to help...
> Le 26/09/2022 à 08:54, reinert a écrit : 
> > Hello, 
> > 
> > This must reveal a compiler error : 
> > ------------------------------------------------------------------------------------------------------- 
> > with Ada.Text_IO; 
> > with Ada.Containers.Vectors; 
> > procedure test1a is 
> > type s_name_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9); 
> > for s_name_type use 
> > (S0 => 0, S1 => 1, S2 => 2, S3 => 3, S4 => 4, 
> > S5 => 5, S6 => 6, S7 => 7, S8 => 8, S9 => 9); 
> > package s_names_p is new Ada.Containers.Vectors 
> > (Index_Type => Positive, Element_Type => s_name_type); 
> > k : integer := 7; 
> > 
> > -- n : constant integer := 7; -- uncomment this line and comment out the line below. 
> > n : constant integer := k; 
> > 
> > s_names: constant s_names_p.Vector := [for i in 3..n => S0]; 
> > begin 
> > Ada.Text_IO.Put_Line(s_names'Image); 
> > end test1a; 
> > ------------------------------------------------------------------------------------------------------- 
> > (compiled using alire and 
> > package Compiler is 
> > for Switches ("ada") use ("-gnatwa", "-gnata", "-gnatX", "-gnatwv"); 
> > end Compiler; 
> > ------------------------------------------------------------------------------------------------------- 
> > 
> > Right? 
> > 
> > reinert
> -- 
> J-P. Rosen 
> Adalog 
> 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX 
> Tel: +33 1 45 29 21 52 
> https://www.adalog.fr

^ permalink raw reply	[relevance 7%]

* Re: Compiler error (2) ?
  2022-09-26  6:54  7% Compiler error (2) ? reinert
@ 2022-09-26  8:34  0% ` J-P. Rosen
  2022-09-26  8:47  7%   ` reinert
  0 siblings, 1 reply; 200+ results
From: J-P. Rosen @ 2022-09-26  8:34 UTC (permalink / raw)


Please give the exact error message, and why you think it could be a 
compiler error. Otherwise, it's hard to help...

Le 26/09/2022 à 08:54, reinert a écrit :
> Hello,
> 
> This must reveal a compiler error :
> -------------------------------------------------------------------------------------------------------
> with Ada.Text_IO;
> with Ada.Containers.Vectors;
> procedure test1a is
>     type s_name_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
>     for s_name_type use
>        (S0 => 0, S1 => 1, S2 => 2, S3 => 3, S4 => 4,
>         S5 => 5, S6 => 6, S7 => 7, S8 => 8, S9 => 9);
>     package s_names_p is new Ada.Containers.Vectors
>       (Index_Type => Positive, Element_Type => s_name_type);
>     k : integer := 7;
> 
> -- n : constant integer := 7; -- uncomment this line and comment out the line below.
>     n : constant integer := k;
> 
>     s_names: constant s_names_p.Vector := [for i in 3..n => S0];
> begin
>     Ada.Text_IO.Put_Line(s_names'Image);
> end test1a;
> -------------------------------------------------------------------------------------------------------
> (compiled using alire and
> package Compiler is
>        for Switches ("ada") use ("-gnatwa", "-gnata", "-gnatX", "-gnatwv");
>     end Compiler;
> -------------------------------------------------------------------------------------------------------
> 
> Right?
> 
> reinert

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52
https://www.adalog.fr


^ permalink raw reply	[relevance 0%]

* Compiler error (2) ?
@ 2022-09-26  6:54  7% reinert
  2022-09-26  8:34  0% ` J-P. Rosen
  0 siblings, 1 reply; 200+ results
From: reinert @ 2022-09-26  6:54 UTC (permalink / raw)


Hello,

This must reveal a compiler error :
-------------------------------------------------------------------------------------------------------
with Ada.Text_IO;
with Ada.Containers.Vectors;
procedure test1a is
   type s_name_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
   for s_name_type use
      (S0 => 0, S1 => 1, S2 => 2, S3 => 3, S4 => 4,
       S5 => 5, S6 => 6, S7 => 7, S8 => 8, S9 => 9);
   package s_names_p is new Ada.Containers.Vectors
     (Index_Type => Positive, Element_Type => s_name_type);
   k : integer := 7;

-- n : constant integer := 7; -- uncomment this line and comment out the line below.
   n : constant integer := k; 

   s_names: constant s_names_p.Vector := [for i in 3..n => S0];
begin
   Ada.Text_IO.Put_Line(s_names'Image);
end test1a;
-------------------------------------------------------------------------------------------------------
(compiled using alire and  
package Compiler is
      for Switches ("ada") use ("-gnatwa", "-gnata", "-gnatX", "-gnatwv");
   end Compiler;
-------------------------------------------------------------------------------------------------------

Right?

reinert

^ permalink raw reply	[relevance 7%]

* Re: Non-standard functions in GNAT's Ada.Containers packages?
  @ 2022-09-16 17:08  8%                 ` Jere
  0 siblings, 0 replies; 200+ results
From: Jere @ 2022-09-16 17:08 UTC (permalink / raw)


On Friday, September 16, 2022 at 12:30:51 PM UTC-4, amado...@gmail.com wrote:
> Jere, ehh.p..., thanks a lot, your complete code was very helpful. 
> For some reason I tried to write for maps as for vectors and it did not pass. 
> I see now some forms do pass. 
> Sorry for the entropy. 
> As you note, still not possible to access the Key with the "of" form. 
> 
> /* 
> And the form
> for (C : My_Maps.Cursor) of My_Map.Iterate loop
> does not pass. Must be "in" 
> */ 
> 
> Thanks all.
 No problem at all.  Yeah, all the standard Ada containers use the "of" form to iterate
over elements and the "in" form to iterate over cursors.  Keys are more like cursors 
from the perspective of the container, so you would need to use some form of "in" 
to get the keys.  

for what it is worth, the example I gave is usable for vectors.  you have to change
names and use append() instead of insert(), but the rest is pretty similar:

*******************************************
    with Ada.Text_IO; use Ada.Text_IO;
    with Ada.Containers.Vectors;
     
    procedure Program is
        package Vectors is new Ada.Containers.Vectors(Positive,Integer);
     
        Vector : Vectors.Vector;
     
    begin
     
        Vector.Append(10);
        Vector.Append(20);
        Vector.Append(30);
        Vector.Append(40);
     
        for Element of Vector loop
            Put_Line(Element'Image);
        end loop;   
    end Program;
**********************************************
Output:
10
 20
 30
 40
*******************************************
IDEONE compiler link:  https://ideone.com/3Ic49d#stdout

So it may depend on how your vector code was originally setup.  
The above is how I typically loop through a vector, which works
for maps and other Ada containers as well.  

Hope that helps!

^ permalink raw reply	[relevance 8%]

* Non-standard functions in GNAT's Ada.Containers packages?
@ 2022-09-14 12:36  6% G.B.
    0 siblings, 1 reply; 200+ results
From: G.B. @ 2022-09-14 12:36 UTC (permalink / raw)


In Ada.Containers.{Kind}s of GCC 11.2, I find functions defined
by the pattern:

   function Empty (Capacity : Count_Type := 1000) return {Kind};

I couldn't find these functions in the LRM's package specifications.

Upon type derivation, then, these functions appear to require
non-portable source text when using GNAT's standard Ada
containers.  For example,

     package Real_Vectors is new Ada.Containers.Vectors (...);
     type Fancy_Vectors is new Real_Vectors.Vector with private;

     18.     type Fancy_Vectors is new Real_Vectors.Vector with record
                  |
         >>> type must be declared abstract or "Empty" overridden
         >>> "Empty" has been inherited at line 14
         >>> "Empty" has been inherited from subprogram at a-convec.ads:125, instance at line 8


While composition would not incur this effect, etc. etc., still
the resulting source text would need to override a "standard" function,
but this function, Empty, might not exist at all when using other
standard Ada compilers.

Am I missing something?

^ permalink raw reply	[relevance 6%]

* Question on in/out parameters
@ 2022-04-30  8:57  7% reinert
  0 siblings, 0 replies; 200+ results
From: reinert @ 2022-04-30  8:57 UTC (permalink / raw)


Hello,

I expected an "out" parameter in a procedure to be like declaring the parameter "from scratch" (with actual initial default value). For my compiler (GNAT Community Edition, May 2021) it seems like the out parameters brings in content from the calling procedure. Should it be like this?

Below is a test program to illustrate.

reinert

with Ada.Containers; use Ada.Containers;
with Ada.Containers.Vectors;
with Ada.Text_IO; use Ada.Text_IO;
procedure test2 is

   package Integer_Vectors is new Ada.Containers.Vectors
       (Index_Type   => Natural, Element_Type => Integer);
   use Integer_Vectors;

   V : Vector := 10 & 20;

   procedure rk_in_out(W : in out Vector) is
   begin
     W.Append(30); W.Append(40);
   end rk_in_out;

   procedure rk_out(W :    out Vector) is
   begin
     W.Clear;  -- I expected this statement to be redundant since W is "out parameter" (try to remove it and see if results remain the same.)?
     W.Append(30); W.Append(40);
   end rk_out;

begin

   New_Line;
   Put ("First V  : ");
   for e of V loop
       Put(e'Image & " ");
   end loop;

   rk_in_out(W => V);
   New_Line;
   Put ("Second V : ");
   for e of V loop
       Put(e'Image & " ");
   end loop;

   rk_out(W => V);
   New_Line;
   Put ("Third V :  ");
   for e of V loop
       Put(e'Image & " ");
   end loop;

end test2;


^ permalink raw reply	[relevance 7%]

* Re: Unchecked_Deallocation with tagged types
  @ 2022-04-18  1:51  6%                       ` Thomas
  0 siblings, 0 replies; 200+ results
From: Thomas @ 2022-04-18  1:51 UTC (permalink / raw)


In article <s5vpul$ldb$1@franka.jacob-sparre.dk>,
 "Randy Brukardt" <randy@rrsoftware.com> wrote:

> "Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
> news:ie8uagFqaf2U1@mid.individual.net...
> > On 2021-04-20 23:32, Jeffrey R. Carter wrote:
> >> On 4/20/21 8:53 PM, Randy Brukardt wrote:
> >>>
> >>> 'Free makes more sense in a new language (an Ada follow-on).
> >>
> >> Right. I don't think it would be a good idea to add it to Ada.
> >>
> >> But I think a new language should not have pointers at all.
> >>
> >> No more radical than not having arrays.
> >
> > It seems to me that a language without arrays and pointers would be very 
> > difficult to use in an embedded, real-time, close-to-HW context. So we 
> > would lose the nice wide-spectrum nature of Ada.

i like "the nice wide-spectrum nature of Ada" :-)
If I got it right, it is the thickness*, that is, it goes both far in 
low level and far in high level.

* Natacha Porte, https://www.youtube.com/watch?v=b5lRyBRk0d8&t=430s 
(during 1:10 - sorry, it's only in french)


> 
> It's important that a new language have a way to interface to existing 
> hardware and software. So there has to be something that maps to C arrays 
> and pointers (and the equivalent for hardware). But that doesn't necessarily 
> have to be something that is used outside of interfacing. An Ada example is 
> Unchecked_Unions -- they exist for interfacing but shouldn't be used 
> otherwise.

i don't know much "exotic things" (for me) like embedded or real-time 
programming,
but i would not take the risk to exclude users who need low level in 
various cases (not only in interfaces),
so i think it would be better to keep a full thickness with the ability 
to go far in low level at any place it is considered usefull.

> A fixed vector type and a raw general access type would do the 
> trick, but those could be something that are almost never used outside of 
> interfacing packages.

an other point here, is the ability to create new structures that could 
be considered as "basic" later.

for example Ada.Containers.Multiway_Trees seems to be based on 
Ada.Containers.Doubly_Linked_Lists,
and i don't know if it could be needed / usefull to have trees based on 
Ada.Containers.Vectors,
but based on Ada.Containers.Ordered_Maps, certainly!

and sometimes using other high level data structures would be enough, 
but probably sometimes it would be non-optimal, and maybe, in the worst 
case, it could be impossible (especially in the event that we had not 
foreseen all the needed high level data structures)


so, i think:

- we could keep arrays as is, no matter if they are rarly used.

- for access types, it would be nice to find a kind of "controlled 
access type" that allows:
  - to access the "raw general access type", as low level type,
    when needed,
  - to need not Unchecked_Deallocation, making automatic Deallocation,
  - and which would not be too much high level
    (for example Ada.Containers.Indefinite_Holders is fine).

-- 
RAPID maintainer
http://savannah.nongnu.org/projects/rapid/

^ permalink raw reply	[relevance 6%]

* Re: specifying only 'First of an index in an array
  @ 2021-02-03 19:29  6% ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2021-02-03 19:29 UTC (permalink / raw)


On 2/3/21 6:47 PM, Mehdi Saada wrote:
> Is there a way, on nominal or genetic array type definition (I mean in generic specifications), to ensure that Index_type'First is always the same, but that arrays can still grow ?

Arrays can't grow in Ada, so I don't know what you're asking. For a sequence 
with a fixed lower bound and variable length you can use Ada.Containers.Vectors.

-- 
Jeff Carter
"Sheriff murdered, crops burned, stores looted,
people stampeded, and cattle raped."
Blazing Saddles
35

^ permalink raw reply	[relevance 6%]

* Re: Lower bounds of Strings
  @ 2021-01-09 10:53  5%                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2021-01-09 10:53 UTC (permalink / raw)


On 2021-01-09 03:18, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:rtaeok$l8b$1@gioia.aioe.org...
>> On 2021-01-08 18:23, Shark8 wrote:
>>> On Thursday, January 7, 2021 at 3:03:54 PM UTC-7, Randy Brukardt wrote:
>>
>>>> Any sort of multiple inheritance (not to mention multiple dispatch)
>>>> requires
>>>> searching a lookup table for the appropriate interface.
>>> Ah.
>>> It appears you're confusing the Ada concept underlying keyword INTERFACE
>>> with the general/abstract notion.
>>> It appears to me that Dmitry is referring to the latter, not the
>>> Ada-construct of INTERFACE, which requires a tagged type.
>>>
>>> I think what he's getting at is something that I considered/proposed here
>>> on C.L.A some years ago, adding the concept of an "ABSTRACT INTERFACE" to
>>> Ada. (IIRC, the proposal I had in mind was to be able to model the
>>> notional meta type-hierarchy; eg: Number ? Universal_Integer ?
>>> System.Integer.)
>>
>> Right, though I do not think that tags can inflict any cost. The situation
>> is same as with array bounds. You do keep bounds when the array is
>> statically constrained. Tag is just another constraint like bounds. It
>> must be handled just same way, removed when statically known. No penalty,
>> unless classes are actually used. I do not know why people always bring
>> dispatch into discussions about static cases.
> 
> The possibility of dynamic dispatch (in some code that doesn't exist yet,
> but *could*) is what is so expensive and is virtually impossible to remove
> after the fact (that is, in an optimizer).

The representation without the tag must be mandatory.

> If you wanted to include a
> declaration that you *never* were going to use any dynamic dispatch,

This declaration is already in the language. Only A'Class dispatches. 
Again, it is like with bounds, only array (... range <>) of ... has 
dynamic bounds. To enforce dispatch one would have to convert to A'Class 
first, that will add the tag to the array's dope vector.

> then
> you could talk try to ignore the possibility. But without some sort of
> dispatch, a defined interface buys you nothing other than complication. It
> doesn't simplify the description and would substantially complicate the
> implementation. What's the point??

Of course it will simplify everything. E.g. our beloved generics. Compare

    generic
       type I is (<>);
       type E is private;
       type A is array (I range <>) of E;

with

    generic
       type A is new Root_Array_Type with private;

or

    package Ada.Containers.Vectors is
       ...
       type Vector is tagged private
          with Constant_Indexing => Constant_Reference,
               Variable_Indexing => Reference,
               Default_Iterator  => Iterate,
               Iterator_Element  => Element_Type;
       -- hundreds of operation declarations

with

    type Vector is new array (Index_Type) of Element_Type with private;
       -- nothing else to declare

Everything in Ada could be formalized in interfaces:

   type Index is new Discrete_Type; -- Same as <>
   type Discrete_Type is abstract new Ordered_Type and Copyable_Type;

and so on.

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

^ permalink raw reply	[relevance 5%]

* Re: Lower bounds of Strings
  2021-01-07  0:17  6%     ` Randy Brukardt
@ 2021-01-07  9:57  0%       ` Dmitry A. Kazakov
    0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2021-01-07  9:57 UTC (permalink / raw)


On 2021-01-07 01:17, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:rt3uv2$1nrd$1@gioia.aioe.org...
>> On 2021-01-06 04:08, Randy Brukardt wrote:
>>> IMHO, "String" shouldn't be an array at all. In a UTF-8 world, it makes
>>> little sense to index into a string - it would be expensive to do it
>>> based
>>> on characters (since they vary in size), and dangerous to do it based on
>>> octets (since you could get part of a character).
>>
>> It will not work. There is no useful integral operations defined on
>> strings. It is like arguing that image is not an array of pixels because
>> you could distort objects in there when altering individual pixels.
>>
>>> The only real solution is to never use String in the first place. A
>>> number
>>> of people are building UTF-8 abstractions to replace String, and I expect
>>> those to become common in the coming years.
>>
>> This will never happen. Ada standard library already has lots of integral
>> operations defined on strings. They are practically never used. The UTF-8
>> (or whatever encoding) abstraction thing simply does not exist.
>>
>>> Indeed, (as I've mentioned before) I would go further and abandon arrays
>>> altogether -- containers cover the same ground (or could easily) -- the
>>> vast
>>> complication of operators popping up much after type declarations,
>>> assignable slices, and supernull arrays all waste resources and cause
>>> oddities and dangers. It's a waste of time to fix arrays in Ada -- just
>>> don't use them.
>>
>> How these containers are supposed to be implemented?
> 
> Built-in to the implementation, of course. Implementing these things in Ada
> is a nice capability, because that allows simple quick-and-dirty
> implementations. But for things that are commonly used, that necessarily
> leads to lousy performance. One has to have at least some special cases even
> for the Ada.Containers to get adequate performance, so there's no problem
> extending that.

OK, they cannot be implemented in this new Ada. How is that different to 
the present status? Drop features and make syntax ugly is that all?

> ...
>> How Stream_Element_Array is supposed to be an opaque container?
> 
> It should already be an opaque container. You use language-defined stream
> attributes to implement user-defined stream attributes - not unportable
> direct byte twiddling.

No, you are talking about stream here, I am about Stream_Element_Array.

>> How file read operation is supposed to assign part of a container?
> 
> ??? Why would you want to do that?

Well, to read a chuck of data from the socket. Where it goes?

> Streaming a bounded vector (which almost
> all existing arrays should be) naturally would read only the active part of
> the vector.

What is active part of vector? Does it have some type? How do I pass it 
to a subprogram?

> Non-streaming reading is left over Ada 83 nonsense; all I/O
> should be built on top of streams (as a practical matter, the vast majority
> is anyway).

No physical I/O is stream with very rare exceptions.

>> You cannot rid of array interface with all its types involved: index,
>> index set (range), element, element set (array). A containers without the
>> array interface cannot replace array. Any language must support them. The
>> problem is that Ada has array interfaces once built-in and as an ugly lame
>> monstrosity of helper tagged types, a mockery of array.
> 
> There no reason that a container interface cannot have those things --
> Ada.Containers.Vectors does.

As array it is unusable.

> The things that Vectors is missing (mainly the
> ability to use enumeration and modular indexes) was a mistake that I
> complained about repeatedly during the design, but I lost on that.

It has all disadvantages of being no array and no advantages of being a 
tagged type. I do not see how two bad could make one good.

>> Array implementation is a fundamental building block of computing.
> 
> Surely. But one does not need the nonsense of requiring an underlying
> implementation (which traditional arrays do) in order to get that building
> block. You always talk about this in terms of an "interface", which is
> essentially the same idea. One cannot have any sort of non-contigious or
> persistent arrays with the Ada interface, since operations like assigning
> into slices are impossible in such representations. One has to give those
> things up in order to have an "interface" rather than the concrete form for
> Ada arrays.

No, one should have interfaces for such operations as well. You cannot 
do that with a single type and single dispatch. That is another reason 
why you cannot replace built-in arrays with anything before you resolve 
the type system issues. The elephant is the room is that you cannot 
spell array type in Ada. So your solution is supposed to be let's have 
no arrays. That is no solution at all.

> I prefer to not call the result an array, since an array implies a
> contiguous in-memory representation. Of course, some vectors will have such
> a representation, but that needs to be a requirement only for vectors used
> for interfacing. (And those should be used rarely.)

And how these special vectors will differ from other vectors? If Read 
takes special vector (does it?) can I pass a non-special vector instead? 
It leaks. Ada 83 resolved all this per compiler magic. Modern Ada has 
nothing more to offer.

>> That does not go either. Of course you could have two languages, one with
>> arrays to implement containers and one without them for end users. But
>> this is neither Ada philosophy nor a concept for any good
>> universal-purpose language.
> 
> Compilers implement arrays in Ada; there is no possibility a user doing it.
> I see no difference between that and having the compiler implement a bounded
> vector instead as the fundamental building block.

See above. Is bounded vector a vector? No, you cannot make it. So you 
are right back with ugly half-baked arrays named bounded vectors and 
even uglier unbounded vectors with zillion generic functions to convert 
one to another.

> You seem fixated on the
> form of declaration (that is a generic package vs. some sort of built-in
> syntax) -- there's no fundamental difference.

If syntax were the only problem it would be easy to resolve by adding it 
to generics. The problem is not syntax but lacking functionality and 
types and subtypes involved. Generics simply cannot do anything 
resembling Ada 83 arrays.

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

^ permalink raw reply	[relevance 0%]

* Re: Lower bounds of Strings
  @ 2021-01-07  0:17  6%     ` Randy Brukardt
  2021-01-07  9:57  0%       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Randy Brukardt @ 2021-01-07  0:17 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:rt3uv2$1nrd$1@gioia.aioe.org...
> On 2021-01-06 04:08, Randy Brukardt wrote:
>> IMHO, "String" shouldn't be an array at all. In a UTF-8 world, it makes
>> little sense to index into a string - it would be expensive to do it 
>> based
>> on characters (since they vary in size), and dangerous to do it based on
>> octets (since you could get part of a character).
>
> It will not work. There is no useful integral operations defined on 
> strings. It is like arguing that image is not an array of pixels because 
> you could distort objects in there when altering individual pixels.
>
>> The only real solution is to never use String in the first place. A 
>> number
>> of people are building UTF-8 abstractions to replace String, and I expect
>> those to become common in the coming years.
>
> This will never happen. Ada standard library already has lots of integral 
> operations defined on strings. They are practically never used. The UTF-8 
> (or whatever encoding) abstraction thing simply does not exist.
>
>> Indeed, (as I've mentioned before) I would go further and abandon arrays
>> altogether -- containers cover the same ground (or could easily) -- the 
>> vast
>> complication of operators popping up much after type declarations,
>> assignable slices, and supernull arrays all waste resources and cause
>> oddities and dangers. It's a waste of time to fix arrays in Ada -- just
>> don't use them.
>
> How these containers are supposed to be implemented?

Built-in to the implementation, of course. Implementing these things in Ada 
is a nice capability, because that allows simple quick-and-dirty 
implementations. But for things that are commonly used, that necessarily 
leads to lousy performance. One has to have at least some special cases even 
for the Ada.Containers to get adequate performance, so there's no problem 
extending that.

...
> How Stream_Element_Array is supposed to be an opaque container?

It should already be an opaque container. You use language-defined stream 
attributes to implement user-defined stream attributes - not unportable 
direct byte twiddling.

> How file read operation is supposed to assign part of a container?

??? Why would you want to do that? Streaming a bounded vector (which almost 
all existing arrays should be) naturally would read only the active part of 
the vector. Non-streaming reading is left over Ada 83 nonsense; all I/O 
should be built on top of streams (as a practical matter, the vast majority 
is anyway).

> You cannot rid of array interface with all its types involved: index, 
> index set (range), element, element set (array). A containers without the 
> array interface cannot replace array. Any language must support them. The 
> problem is that Ada has array interfaces once built-in and as an ugly lame 
> monstrosity of helper tagged types, a mockery of array.

There no reason that a container interface cannot have those things --  
Ada.Containers.Vectors does. The things that Vectors is missing (mainly the 
ability to use enumeration and modular indexes) was a mistake that I 
complained about repeatedly during the design, but I lost on that.

> Array implementation is a fundamental building block of computing.

Surely. But one does not need the nonsense of requiring an underlying 
implementation (which traditional arrays do) in order to get that building 
block. You always talk about this in terms of an "interface", which is 
essentially the same idea. One cannot have any sort of non-contigious or 
persistent arrays with the Ada interface, since operations like assigning 
into slices are impossible in such representations. One has to give those 
things up in order to have an "interface" rather than the concrete form for 
Ada arrays.

I prefer to not call the result an array, since an array implies a 
contiguous in-memory representation. Of course, some vectors will have such 
a representation, but that needs to be a requirement only for vectors used 
for interfacing. (And those should be used rarely.)

> That does not go either. Of course you could have two languages, one with 
> arrays to implement containers and one without them for end users. But 
> this is neither Ada philosophy nor a concept for any good 
> universal-purpose language.

Compilers implement arrays in Ada; there is no possibility a user doing it. 
I see no difference between that and having the compiler implement a bounded 
vector instead as the fundamental building block. You seem fixated on the 
form of declaration (that is a generic package vs. some sort of built-in 
syntax) -- there's no fundamental difference. There are many Ada packages 
that are built-in to compilers (for Janus/Ada, these include System and 
Ada.Exceptions and Ada.Assertions) -- there's no body or even source of 
these to be seen.

We're not even talking about different syntax for the use of vectors (and it 
would be easy to have some syntax sugar for declarations - we already have a 
proposal on those lines for Ada). Indeed, in a new language, one would 
certainly call these "array" containers (couldn't do that in Ada as the word 
"array" is reserved).

Sometimes, one has to step back and look at the bigger picture and not 
always at the way things have always been done. Arrays (at least as defined 
in Ada) have outlived their usefulness.

                          Randy.




^ permalink raw reply	[relevance 6%]

* Re: Proposal: Auto-allocation of Indefinite Objects
  @ 2020-07-27 20:31  7%     ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2020-07-27 20:31 UTC (permalink / raw)


On 7/27/20 7:48 PM, Brian Drummond wrote:
> 
> Is there any way we could generalise the (storage, access and lifetime
> aspects of) Unbounded_String for unconstrained arrays and discriminated
> records in such a way that Unbounded_String can be a simple instantiation
> of one of these?

Ada.Strings.Unbounded can be considered a combination of 
Ada.Containers.Indefinite_Holders instantiated for String and 
Ada.Containers.Vectors instantiated with Positive and Character, with some 
additional operations added.

The To_String and To_Unbounded_String operations of Unbounded_String are similar 
to the Element and Replace_Element operations of Holder, which do not exist for 
Vector.

The indexed operations of Unbounded_String are similar to the indexed operations 
of Vector, which do not exist for Holder.

If Ada.Containers.Vectors had an additional generic formal type

    type Fixed is array (Index_Type range <>) of Element_Type;

and 2 new operations

    function To_Fixed (From : Vector) return Fixed;
    function To_Vector (From : Fixed) return Vector;

then we wouldn't need Ada.Strings.Unbounded.

-- 
Jeff Carter
"Blessed is just about anyone with a vested interest in the status quo."
Monty Python's Life of Brian
73

^ permalink raw reply	[relevance 7%]

* Re: How can I get this data into the .data section of the binary?
  @ 2020-06-16 16:11  5%           ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2020-06-16 16:11 UTC (permalink / raw)


On 16/06/2020 17:43, Luke A. Guest wrote:
> On 16/06/2020 16:21, Dmitry A. Kazakov wrote:
>> On 16/06/2020 16:42, Luke A. Guest wrote:
>>> On 16/06/2020 15:25, Dmitry A. Kazakov wrote:
>>>> On 16/06/2020 16:14, Niklas Holsti wrote:
>>>
>>>>> I have no idea if this will help you -- the types in our case were
>>>>> much simpler -- but you might try it with a small subset of your
>>>>> package:
>>>>>
>>>>>       Pixel_Format_Unknown     : constant Pixel_Format_Names :=
>>>>>         (True, (NUL, NUL, NUL, NUL));
>>>>>
>>>>> (assuming "use Ada.Characters.Latin_1").
>>>>
>>>> That is interesting. Was there the "others =>" part?
>>>>
>>>> I can imagine that with "others => NUL" a static zeroed section were
>>>> used with other parts written upon it during start.
>>>>
>>>> P.S. I hope more people now see why compile-time subprograms are
>>>> necessary.
>>>>
>>>
>>> I don't think Ada needs compile-time subprograms, it just needs to
>>> recognise actual static data which can be generated at compile time,
>>
>> Without calling subprograms? That is not possible in 99% of use cases.
> 
> Course it is. The compiler will translate the code into data.

Consider an array filled with Fibonacci numbers or a parser's tokens 
table or a constant instance of Ada.Containers.Vectors. It is a big 
issue for small embedded systems with instant booting time requirement.

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

^ permalink raw reply	[relevance 5%]

* Re: Different aliasing rules for containers?
  2020-02-20 13:36  0% ` joakimds
@ 2020-02-20 13:47  0%   ` Martin B. B.
  0 siblings, 0 replies; 200+ results
From: Martin B. B. @ 2020-02-20 13:47 UTC (permalink / raw)


On Thursday, 20 February 2020 14:36:38 UTC+1, joak...@kth.se  wrote:
> Den torsdag 20 februari 2020 kl. 13:24:37 UTC+1 skrev Martin B. B.:
> > The following code:
> > 
> > with Ada.Containers.Vectors;
> > with Ada.Text_IO;
> > 
> > procedure Test is
> > 
> >    package IO renames Ada.Text_IO;
> > 
> >    type Obj is record
> >       Id : Integer;
> >    end record;
> > 
> >    package Obj_Vectors is new Ada.Containers.Vectors
> >      (Index_Type   => Positive,
> >       Element_Type => Obj);
> >    
> >    use type Obj_Vectors.Vector;
> >       
> >    Objects : Obj_Vectors.Vector := Obj'(Id => 0) & Obj'(Id => 1) & Obj'(Id => 2);
> > 
> > begin
> >    for O of Objects loop
> >       O.Id := 999;
> >    end loop;
> >    
> >    for O of Objects loop
> >       IO.Put_Line (Integer'Image (O.Id));
> >    end loop;
> > end Test;
> > 
> > Using GNAT Community 2019 (20190517-83) produces the following output:
> >  999
> >  999
> >  999
> > 
> > When looking at the Ada.Containers.Vectors package specification, I see the following:
> >    type Vector is tagged private
> >    with
> >       Constant_Indexing => Constant_Reference,
> >       Variable_Indexing => Reference,
> >       Default_Iterator  => Iterate,
> >       Iterator_Element  => Element_Type;
> > 
> > However, both the `Rerefence` and `Constant_Reference` functions takes aliased parameters:
> >    function Reference
> >      (Container : aliased in out Vector;
> >       Position  : Cursor) return Reference_Type;
> > 
> > My question is then: How is the code above possible then, when my `Objects` vector is not aliased? Shouldn't the compiler complain that I haven't declared `Objects` as being aliased?
> > 
> > Even creating my own procedure that takes a `V : aliased Obj_Vectors.Vector` still produces no aliasing errors when passing it a non-aliased vector.
> > 
> > This code:
> > with Ada.Text_IO;
> > 
> > procedure Test is
> > 
> >    package IO renames Ada.Text_IO;
> >    
> >    procedure Takes_Aliased_Integer (X : aliased Integer);
> > 
> >    procedure Takes_Aliased_Integer (X : aliased Integer) is
> >    begin
> >       null;
> >    end Takes_Aliased_Integer;
> > 
> >    My_Int : Integer := 123;
> > 
> > begin
> >    Takes_Aliased_Integer (My_Int);
> > end Test;
> > 
> > However, correctly(?) generates the following compiler error: "actual for aliased formal "X" must be aliased object".
> > 
> > So, what exactly is going on here? Am I missing something?
> 
> Hi Martin,
> 
> Could it be because Obj_Vectors.Vector is a tagged type and is therefore always passed by reference in subprogram calls and that implies it is aliased?
> 
> Best regards,
> Joakim

Ah, it seems you are correct! I was not aware of this difference between tagged and non-tagged types.

It seems to be what is mentioned here in the reference manual: "Finally, a formal parameter or generic formal object of a tagged type is defined to be aliased" (http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-3-10.html#p9)

Thank you for the help :)

^ permalink raw reply	[relevance 0%]

* Re: Different aliasing rules for containers?
  2020-02-20 12:24  7% Different aliasing rules for containers? Martin B. B.
@ 2020-02-20 13:36  0% ` joakimds
  2020-02-20 13:47  0%   ` Martin B. B.
  0 siblings, 1 reply; 200+ results
From: joakimds @ 2020-02-20 13:36 UTC (permalink / raw)


Den torsdag 20 februari 2020 kl. 13:24:37 UTC+1 skrev Martin B. B.:
> The following code:
> 
> with Ada.Containers.Vectors;
> with Ada.Text_IO;
> 
> procedure Test is
> 
>    package IO renames Ada.Text_IO;
> 
>    type Obj is record
>       Id : Integer;
>    end record;
> 
>    package Obj_Vectors is new Ada.Containers.Vectors
>      (Index_Type   => Positive,
>       Element_Type => Obj);
>    
>    use type Obj_Vectors.Vector;
>       
>    Objects : Obj_Vectors.Vector := Obj'(Id => 0) & Obj'(Id => 1) & Obj'(Id => 2);
> 
> begin
>    for O of Objects loop
>       O.Id := 999;
>    end loop;
>    
>    for O of Objects loop
>       IO.Put_Line (Integer'Image (O.Id));
>    end loop;
> end Test;
> 
> Using GNAT Community 2019 (20190517-83) produces the following output:
>  999
>  999
>  999
> 
> When looking at the Ada.Containers.Vectors package specification, I see the following:
>    type Vector is tagged private
>    with
>       Constant_Indexing => Constant_Reference,
>       Variable_Indexing => Reference,
>       Default_Iterator  => Iterate,
>       Iterator_Element  => Element_Type;
> 
> However, both the `Rerefence` and `Constant_Reference` functions takes aliased parameters:
>    function Reference
>      (Container : aliased in out Vector;
>       Position  : Cursor) return Reference_Type;
> 
> My question is then: How is the code above possible then, when my `Objects` vector is not aliased? Shouldn't the compiler complain that I haven't declared `Objects` as being aliased?
> 
> Even creating my own procedure that takes a `V : aliased Obj_Vectors.Vector` still produces no aliasing errors when passing it a non-aliased vector.
> 
> This code:
> with Ada.Text_IO;
> 
> procedure Test is
> 
>    package IO renames Ada.Text_IO;
>    
>    procedure Takes_Aliased_Integer (X : aliased Integer);
> 
>    procedure Takes_Aliased_Integer (X : aliased Integer) is
>    begin
>       null;
>    end Takes_Aliased_Integer;
> 
>    My_Int : Integer := 123;
> 
> begin
>    Takes_Aliased_Integer (My_Int);
> end Test;
> 
> However, correctly(?) generates the following compiler error: "actual for aliased formal "X" must be aliased object".
> 
> So, what exactly is going on here? Am I missing something?

Hi Martin,

Could it be because Obj_Vectors.Vector is a tagged type and is therefore always passed by reference in subprogram calls and that implies it is aliased?

Best regards,
Joakim

^ permalink raw reply	[relevance 0%]

* Different aliasing rules for containers?
@ 2020-02-20 12:24  7% Martin B. B.
  2020-02-20 13:36  0% ` joakimds
  0 siblings, 1 reply; 200+ results
From: Martin B. B. @ 2020-02-20 12:24 UTC (permalink / raw)


The following code:

with Ada.Containers.Vectors;
with Ada.Text_IO;

procedure Test is

   package IO renames Ada.Text_IO;

   type Obj is record
      Id : Integer;
   end record;

   package Obj_Vectors is new Ada.Containers.Vectors
     (Index_Type   => Positive,
      Element_Type => Obj);
   
   use type Obj_Vectors.Vector;
      
   Objects : Obj_Vectors.Vector := Obj'(Id => 0) & Obj'(Id => 1) & Obj'(Id => 2);

begin
   for O of Objects loop
      O.Id := 999;
   end loop;
   
   for O of Objects loop
      IO.Put_Line (Integer'Image (O.Id));
   end loop;
end Test;

Using GNAT Community 2019 (20190517-83) produces the following output:
 999
 999
 999

When looking at the Ada.Containers.Vectors package specification, I see the following:
   type Vector is tagged private
   with
      Constant_Indexing => Constant_Reference,
      Variable_Indexing => Reference,
      Default_Iterator  => Iterate,
      Iterator_Element  => Element_Type;

However, both the `Rerefence` and `Constant_Reference` functions takes aliased parameters:
   function Reference
     (Container : aliased in out Vector;
      Position  : Cursor) return Reference_Type;

My question is then: How is the code above possible then, when my `Objects` vector is not aliased? Shouldn't the compiler complain that I haven't declared `Objects` as being aliased?

Even creating my own procedure that takes a `V : aliased Obj_Vectors.Vector` still produces no aliasing errors when passing it a non-aliased vector.

This code:
with Ada.Text_IO;

procedure Test is

   package IO renames Ada.Text_IO;
   
   procedure Takes_Aliased_Integer (X : aliased Integer);

   procedure Takes_Aliased_Integer (X : aliased Integer) is
   begin
      null;
   end Takes_Aliased_Integer;

   My_Int : Integer := 123;

begin
   Takes_Aliased_Integer (My_Int);
end Test;

However, correctly(?) generates the following compiler error: "actual for aliased formal "X" must be aliased object".

So, what exactly is going on here? Am I missing something?

^ permalink raw reply	[relevance 7%]

* yes another gnat bug (inherited tagged type as record field is too much for gnat??)
@ 2019-11-22 13:26  4% gerrshapovalov
  0 siblings, 0 replies; 200+ results
From: gerrshapovalov @ 2019-11-22 13:26 UTC (permalink / raw)


Hello,

This bug gets triggered while trying to use a tiny "list library", that provides a uniform interface for an indexed/iterable storage a-la Ada.Containers.Vectors, that can be implemented in various ways: using A.C.Vecotrs internally or even plain "fixed" or "bounded" arrays..

This "library" is a part of ada_composition demo, now made into a stnandalone library, with tests as separate package, and can be found here:
https://github.com/gerr135/ada_composition

The lib itself is under ada_lists
and tests for the lib are under ada_lists_tests


Everything works just fine,.. - as long as I use these lists as "plain variables". However when such list is uses as a record field, gnat just commits suicide trying to compile it. 

Basically:

with Lists.Fixed;

package PL  is new Lists(Natural, Positive);
package PLF is new PL.Fixed;

LS : PLF.List(5);

type FRec (N : Positive) is record
    f : PLF.List(N);
end record;

LC : FRec(5);


LS(1)   := 1; -- works fine
LC.f(1) := 1; -- triggers gnat bug

+===========================GNAT BUG DETECTED==============================+
| Community 2019 (20190517-83) (x86_64-pc-linux-gnu) Storage_Error stack overflow or erroneous memory access

The code in the "library" is pretty much minimal (needed to implements indexed access and iteration), and the tests are just repeated blocks or basic code to test assignment and iteration (in the form of indexed and of loops).

So, the easiest way to reproduce this should be to just clone the project mentioned above ( https://github.com/gerr135/ada_composition )
and then:
cd ada_lists_tests
make

Quite "weirdly" the stock A.C.Vectors work fine as record fields. However, is this due to
1. them being "proper" types rather than descendants of some interface
2. some ACT black magic in their implementation (they do use locks and Unrestricted_Access) in the corresponding bodies, I looked)
is not quite clear to me..

Am I overlooking something here? 
This should be a really common use case, a very basic composition idea:
1. do all the algorithmic stuff at the "higher level", using abstract data accessor methods
2. Defer data storage and other implementation details to child packages..

Yes every time I am trying to do a very basic separation of this kind I trigger yet another gnat bug :(.

^ permalink raw reply	[relevance 4%]

* Funny (so to say...) interaction of "not null" and Vectors?
@ 2019-10-08 15:46  6% mockturtle
  0 siblings, 0 replies; 200+ results
From: mockturtle @ 2019-10-08 15:46 UTC (permalink / raw)


Dear.all,
I am getting crazy over a mysterious bug (that gives mysterious exceptions) that seems to boil down to an interaction between "not null" specification and vectors.

This is an over simplified version of my case.  I would like to know if my hypothesis makes sense.

---  BEGIN ----
type Int is interface;
type Class_Access is not null access all Int'Class;  --  NOTE: not null

type Rec is -- A record with a not null component
  record 
     Acc : Class_Access;  -- This forces me to initialize it
  end record; 

package Vec is new Ada.Containers.Vectors(Positive, Rec);  
-- Vectors that have as elements records with a "not null access" field
--- END ---

It seems that the procedure Append from Vec dies with a "access check failed."  By looking into the GNAT implementation, I see that the Vector is implemented using a dynamically allocated array of Rec (in this case).  When I do Append, the procedure re-allocate the array to make room for the new entry.  My suspect is that the dynamically created array can have some null access value, causing the error.

Does this make any sense?  If yes, I'll remove the "not null" requirement.

Thank you in advance 

Riccardo 

^ permalink raw reply	[relevance 6%]

* Re: How to access Vector.Index_Type?
  2019-03-17 20:43  7% How to access Vector.Index_Type? jakub.dabek
                   ` (2 preceding siblings ...)
  2019-03-18  5:27  0% ` J-P. Rosen
@ 2019-03-18 19:35  0% ` Jeffrey R. Carter
  3 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2019-03-18 19:35 UTC (permalink / raw)


On 3/17/19 9:43 PM, jakub.dabek@gmail.com wrote:
> I have the following program
> 
>      with Ada.Containers.Vectors;
> 
>      procedure Test is
>          package MyVec is new Ada.Containers.Vectors(Natural, Natural);
>          Var : MyVec.Index_Type;
>      begin
>          null;
>      end;
> 
> I get the following error:
> "Index_Type" is not a visible entity of "MyVec"
> 
> How can I access the index type (`Element_Type` gives the same error message), without just writing `Natural`?

This is refreshing. Usually people complain that Ada makes them type too much. 
It's unusual to see someone complain that Ada makes them type less than they want.

If you are dealing with pkg Myvec, Ada presumes that you will look at the 
instantiation and see that it says

Index_Type => Natural

and use Natural when you want an index.

-- 
Jeff Carter
"What I wouldn't give for a large sock with horse manure in it."
Annie Hall
42

^ permalink raw reply	[relevance 0%]

* Re: How to access Vector.Index_Type?
  2019-03-18  5:27  0% ` J-P. Rosen
@ 2019-03-18  8:31  0%   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2019-03-18  8:31 UTC (permalink / raw)


On 2019-03-18 06:27, J-P. Rosen wrote:
> Le 17/03/2019 à 21:43, jakub.dabek@gmail.com a écrit :
>> I have the following program
>>
>>      with Ada.Containers.Vectors;
>>
>>      procedure Test is
>>          package MyVec is new Ada.Containers.Vectors(Natural, Natural);
>>          Var : MyVec.Index_Type;
>>      begin
>>          null;
>>      end;
>>
>> I get the following error:
>> "Index_Type" is not a visible entity of "MyVec"
>>
>> How can I access the index type (`Element_Type` gives the same error 
>> message), without just writing `Natural`?
>>
> Why would you do that? If you instantiate Vectors on Natural, it's 
> because you want a vector of Natural! Therefore it makes sense to use 
> Natural. The name "Index_Type" is a formal, not an actual type, it's 
> just the package's business.

surely for maintenance and code quality reasons. In the example 
everything is clear, but in other (more realistic) scenarios the package 
MyVec might come from other packages only to be used in Test. The 
procedure Test must then use the least possible assumption about the 
index type and be ready to the cases when the type would change, e.g. 
become an enumeration type.

P.S. It is a longstanding issue with visibility of formal generic 
parameters. Anybody who used generics was hit by it more than once. I 
don't know if anything was attempted recently to fix that. A life-hack 
(that does not apply to existing packages) was/is to rename or subtype 
each formal parameter of the generic:

    generic
       type T is <>;
       with package Bar ...
    package Foo is
       subtype The_T is T;
       package The_Bar renames Bar;

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

^ permalink raw reply	[relevance 0%]

* Re: How to access Vector.Index_Type?
  2019-03-17 20:43  7% How to access Vector.Index_Type? jakub.dabek
  2019-03-17 21:25  0% ` Simon Wright
  2019-03-18  4:17  5% ` gautier_niouzes
@ 2019-03-18  5:27  0% ` J-P. Rosen
  2019-03-18  8:31  0%   ` Dmitry A. Kazakov
  2019-03-18 19:35  0% ` Jeffrey R. Carter
  3 siblings, 1 reply; 200+ results
From: J-P. Rosen @ 2019-03-18  5:27 UTC (permalink / raw)


Le 17/03/2019 à 21:43, jakub.dabek@gmail.com a écrit :
> I have the following program
> 
>      with Ada.Containers.Vectors;
> 
>      procedure Test is
>          package MyVec is new Ada.Containers.Vectors(Natural, Natural);
>          Var : MyVec.Index_Type;
>      begin
>          null;
>      end;
> 
> I get the following error:
> "Index_Type" is not a visible entity of "MyVec"
> 
> How can I access the index type (`Element_Type` gives the same error message), without just writing `Natural`?
> 
Why would you do that? If you instantiate Vectors on Natural, it's 
because you want a vector of Natural! Therefore it makes sense to use 
Natural. The name "Index_Type" is a formal, not an actual type, it's 
just the package's business.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

^ permalink raw reply	[relevance 0%]

* Re: How to access Vector.Index_Type?
  2019-03-17 20:43  7% How to access Vector.Index_Type? jakub.dabek
  2019-03-17 21:25  0% ` Simon Wright
@ 2019-03-18  4:17  5% ` gautier_niouzes
  2019-03-18  5:27  0% ` J-P. Rosen
  2019-03-18 19:35  0% ` Jeffrey R. Carter
  3 siblings, 0 replies; 200+ results
From: gautier_niouzes @ 2019-03-18  4:17 UTC (permalink / raw)


>         package MyVec is new Ada.Containers.Vectors(Natural, Natural);
>         Var : MyVec.Index_Type;

Try:
  subtype My_Index is Natural;
  subtype My_Element is Natural;
  package MyVec is new Ada.Containers.Vectors(My_Index, My_Element);
  Var : My_Index; 


^ permalink raw reply	[relevance 5%]

* Re: How to access Vector.Index_Type?
  2019-03-17 20:43  7% How to access Vector.Index_Type? jakub.dabek
@ 2019-03-17 21:25  0% ` Simon Wright
  2019-03-18  4:17  5% ` gautier_niouzes
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 200+ results
From: Simon Wright @ 2019-03-17 21:25 UTC (permalink / raw)


jakub.dabek@gmail.com writes:

> I have the following program
>
>     with Ada.Containers.Vectors;
>
>     procedure Test is
>         package MyVec is new Ada.Containers.Vectors(Natural, Natural);
>         Var : MyVec.Index_Type;
>     begin
>         null;
>     end;
>
> I get the following error:
> "Index_Type" is not a visible entity of "MyVec"
>
> How can I access the index type (`Element_Type` gives the same error
> message), without just writing `Natural`?

You could use

   subtype My_Index_Type is MyVec.Extended_Index
     range MyVec.Extended_Index'First + 1 .. MyVec.Extended_Index'Last;


^ permalink raw reply	[relevance 0%]

* How to access Vector.Index_Type?
@ 2019-03-17 20:43  7% jakub.dabek
  2019-03-17 21:25  0% ` Simon Wright
                   ` (3 more replies)
  0 siblings, 4 replies; 200+ results
From: jakub.dabek @ 2019-03-17 20:43 UTC (permalink / raw)


I have the following program 

    with Ada.Containers.Vectors;

    procedure Test is
        package MyVec is new Ada.Containers.Vectors(Natural, Natural);
        Var : MyVec.Index_Type;
    begin
        null;
    end;

I get the following error:  
"Index_Type" is not a visible entity of "MyVec"  

How can I access the index type (`Element_Type` gives the same error message), without just writing `Natural`?

^ permalink raw reply	[relevance 7%]

* Re: class wide iterable (and indexable)
  2019-01-02 15:48  3% class wide iterable (and indexable) George Shapovalov
  2019-01-02 17:39  4% ` Simon Wright
@ 2019-01-26 22:11  3% ` George Shapovalov
  1 sibling, 0 replies; 200+ results
From: George Shapovalov @ 2019-01-26 22:11 UTC (permalink / raw)


Original poster here.
I think I did it again - that is broke gnat again. 

But first a small update: I have cleaned up and systematized the original code somewhat and added the description. Plus I added the complete "demo" code of the basic mix-in situations. No proper description yet though. The general idea is to create a small depository of common composition situations, to have some base tested code that can be expanded upon.. Two sample compositions are implemented in the code already: the basic mix-ins and the "list interface" over which Ada.Containers.Vectors.Vector can be directly overlayed (among other implementations).
The link to the project is here:
https://github.com/gerr135/ada_composition
(renamed from original ada_gems to avoid name clash with existing Ada Gems by AdaCore).

In trying to expand on that last example - the indexable/iterable and overlayable by existing type interface, I have stumbled upon a rather weird behavior of compiled code. The expansion deals with trying to tie a type hierarchy to the hierarchy of list implementations - not to have a single generic type at the top and children units using the same. Instead this code has a generic interface at the top, and children take specific types implementing interface at the top. This works fine (with minimal code changes in the "library" itself from the previous case) for the basic composition types (record encapsulating wither array of ACV.Vector). But when I try to pass ACV.Vector overlais directly over interface as a generic parameter, it seems the compiler gets confused. While passing the constructed Vector into the List object it raises run-time exception:
raised PROGRAM_ERROR : adjust/finalize raised STORAGE_ERROR: System.Memory.Alloc: heap exhausted

which is rather weird in itself. What's more, a simple whitespace change - splitting the line of code directly above into two (inserting line break between two trivial TEXT_IO ops that are in the same line in the code) changes that error into:
raised PROGRAM_ERROR : adjust/finalize raised STORAGE_ERROR: stack overflow or erroneous memory access

The line of code in question is this:
ld(i) := Base_Interface'Class(set_idx_vector(i));

the setter runs fine (and identical setter for a differently composed version of the base type completes fine *and* allows the constructed object to be passed), but attempt to assign the constructed object to the List container blows up with that STORAGE_ERROR. Please note: only the last variant is affected, that is List composition directly overlaying ACV.Vector over List_Interface, *but not* a more common encapsulation having ACV.Vector a record entry.

Unfortunately. as before, I cannot post just a line or two of code that would reproduce the entire situation. Providing indexing and iteration for the entire type hierarchy takes some code. Please see this specific link for the appropriate part:
https://github.com/gerr135/ada_composition/tree/master/list_combo

This *is* the minimal code that reproduces the situation as far as I can tell..

I cannot see why this specific variant would be "wrong" in some way - the overal interface is the same for all 3 variants. Plus that weird behavior (sensitivity to whitespace) makes me suspect some problem with gnat here. But maybe I overlooked something.
Any ideas are appreciated. 
Thank you!


^ permalink raw reply	[relevance 3%]

* Why forbid local generic instantiations?
@ 2019-01-25  9:43  4% joakimds
  0 siblings, 0 replies; 200+ results
From: joakimds @ 2019-01-25  9:43 UTC (permalink / raw)


Hi!

Consider the following code:

procedure Main is
   package Integer_Vectors is new Ada.Containers.Vectors (Positive, Integer);
begin
   null;
end Main;

It has a generic package instantiation local to the subprogram Main and not defined on package level. Both in AdaControl and GNATCheck there are rules to forbid local generic instantiations.

For example GNATCheck:
23.7.25 Generics_In_Subprograms

 Flag each declaration of a generic unit in a subprogram. Generic declarations in the bodies of generic subprograms are also flagged. A generic unit nested in another generic unit is not flagged. If a generic unit is declared in a local package that is declared in a subprogram body, the generic unit is flagged. 

This rule has no parameters.




Using AdaControl one can use the following rule to detect insantiations of generic packages/subprograms:
5.10 Declarations

This rule controls usage of various kinds of declarations, possibly only those occurring at specified locations. 
...



Why is it considered bad practise to use local generic instantiations? Within the C++ Community, limiting the use of templates doesn't seem an issue. On the contrary, going all in with template metaprogramming is the norm.

Does local generic instantiations have a performance penalty? Is it something that may be error-prone? Limit cross-compiler compatibility? Why does the rule exist to ban local instantiations? I've been googling/searching the web for an answer to this question but have not found an explanation. Does anybody know?

Best regards,
Joakim


^ permalink raw reply	[relevance 4%]

* Re: class wide iterable (and indexable)
  @ 2019-01-06  9:34  5%                 ` George Shapovalov
  0 siblings, 0 replies; 200+ results
From: George Shapovalov @ 2019-01-06  9:34 UTC (permalink / raw)


> > You can using a Mixin Generic along with the interface.  Consider the
> > following example:
> >   <SNIPPED>
> 
> And if you don't like the Mixin method, you can do something a bit closer to
> composition and Rust's model 
Thank you!
Yes, this does the job done (and I believe the 1st one was what Dmitry already have shown above), achieving the effect of in-mixing overridable methods. However allowing interfaces to have non0bull or abstract primitives (obviously referencing onyl existing entities, just like class-wide methods do already anyway) would have been much less cumbersome and much more elegant and readable to begin with..

But this was just a sidenote to that discussion. My original intention was to attempt to move the existing type (that would serve as a top of type hierarchy normally) to the side of a new type tree - which is not that "topologically different" from the mix-in equiliristic, just a bit different way to glue things together. The complicating circumstance in that specific case (which prompted my original post) was to provide indexing/iteration to the entire type tree and then glue Ada.Containers.Vectors right over it, which finally succeeded after more digging through aspects and Ada standard library internals.

Tanks to everybody for informative comments!

^ permalink raw reply	[relevance 5%]

* Re: class wide iterable (and indexable)
  @ 2019-01-05 18:17  4%               ` George Shapovalov
  0 siblings, 0 replies; 200+ results
From: George Shapovalov @ 2019-01-05 18:17 UTC (permalink / raw)


On Saturday, January 5, 2019 at 11:07:57 AM UTC+1, Dmitry A. Kazakov wrote:
> That is because compilers are no longer large software, not even 
> medium-size (:-)). My current project takes a half of week to recompile 
> from scratch.
Sorry to break up this "high opinions" discussion, it is as usual interesting to see varying points of view. Incidentally, having done a few long-standing projects and having maintained Ada in Gentoo Linux (which, in Gentoo's case, implies digging deep into gcc toolchain inner workings), I am of similar to Drmitry's opinion on this point (even though gcc, while bigger than Janus Ada, is still is nowhere near that kind of scale of course).

Nonetheless, back to the original point.
A small update on the original issue:

I have finally had some time to wrap my head around this issue a bit more and I have completed the implementation. Now it builds and tests fine for all cases - specific types and class-wide vars alike. The issue was not just some simple omission. In fact there was not just a single issue - complete implementation required implementing parallel type hierarchies (although with minimum of duplicated code - only for illustration purpose in this case; could be tied up even more, see the comments in the code if anybody is interested by any chance). I essentially ended up reimplementing Ada "standard library", of course in a very simplistic variant, demo-like.  Still, I managed to glue Ada.Containers.Vectors.Vector right over the List_Interface, thus exposing ACV.Vector's primitives directly without extra glue needed. The corresponding code is in the master of:
https://github.com/gerr135/ada_gems/tree/master/list_iface

While digging, I tried alternatives, one of which "hides" the ACV.Vector inside a record - a more classical approach, easier to comprehend (even though the code is mostly the same, less than 10 lines of difference). This code is in "in_rec" branch:
https://github.com/gerr135/ada_gems/tree/in_rec/list_iface


Finally, at some point while testing different things I managed to break gnat, causing it to spill out that gnat Bug message. Relevant code and error message are in yet another branch, here:
https://github.com/gerr135/ada_gems/tree/gnat_bug_01/list_iface

the bug message text is in the "bug_info.txt" file at the top of the list_iface folder..

Is this something already well known or should I report this bug to AdaCore?


^ permalink raw reply	[relevance 4%]

* Re: class wide iterable (and indexable)
  2019-01-02 18:11  6%   ` George Shapovalov
  2019-01-03  8:52  0%     ` Simon Wright
@ 2019-01-03 22:56  0%     ` Randy Brukardt
    1 sibling, 1 reply; 200+ results
From: Randy Brukardt @ 2019-01-03 22:56 UTC (permalink / raw)


"George Shapovalov" <gshapovalov@gmail.com> wrote in message 
news:2a6929c5-72fa-4d84-953a-44ea4597ab38@googlegroups.com...
...
>I did see in the Ada.Containers.Vectors code two versions defined, however 
>I was not
>clear on why, especially since both the Ada Gem 10x (I forgot now exact 
>number) and
>Ada Rationale for 2012 seem to only provide one, with a Cursor.

Vectors support both indexing by an integer and reference via a cursor. 
Usually, the List container is a better example for cursor operations 
because it doesn't have the confusion of (direct) indexing involved.

...
>On a related note, I was rather surprised that the related types in 
>Ada.Containers do not
>form such a hierarchy. Say both Ada.Containers.Vectors and 
>Indefinite_Vectors (and
>especially now with addition of Bounded_Vectors too) all could derive from 
>a common
>ancestor that could be used to implement common functionality and let end 
>user chose
>the desired data storage model..

Because that would substantially harm ease-of-use. You'd have to write 
multiple instantiations to create any container. It's annoying enough (to 
some, at least) to have to write one.

Besides, interfaces are (nearly) useless (and especially so for this sort of 
usage, where some part has to be generic). They add a lot of runtime 
overhead that doesn't actually get used in real programs. For example, we 
did do what you suggest for the queue containers. Irrelevant thought: that's 
probably why I have yet to hear of anyone actually using one of them. :-) 
Back to the point: there's virtually no circumstance where you'd use more 
than one type of queue with any specific data type, so the generality buys 
essentially nothing. (The only real use is in generic units, but those could 
have been handled with formal packages just as well.) So you're paying a 
substantial price in code size and time, but no real gain.

Perhaps if Ada allowed multiple controlling parameters of different tagged 
types, then there might be more use. But with the existing Ada rules, 
interfaces can only be useful if the profiles are fixed (non-generic) and 
are still reusable -- that doesn't happen that often.

                               Randy.





^ permalink raw reply	[relevance 0%]

* Re: class wide iterable (and indexable)
  2019-01-02 18:11  6%   ` George Shapovalov
@ 2019-01-03  8:52  0%     ` Simon Wright
  2019-01-03 22:56  0%     ` Randy Brukardt
  1 sibling, 0 replies; 200+ results
From: Simon Wright @ 2019-01-03  8:52 UTC (permalink / raw)


George Shapovalov <gshapovalov@gmail.com> writes:

> Thanks!
> I'll try adding this and see if I can get around that invalid
> interface conversion.
>
> I did see in the Ada.Containers.Vectors code two versions defined,
> however I was not clear on why, especially since both the Ada Gem 10x
> (I forgot now exact number) and Ada Rationale for 2012 seem to only
> provide one, with a Cursor.

ARM A.18.2(34.3)ff[1] has both forms.

> However, from your response (also my general impression while digging
> through the iterables workings) is that this is not a common way to
> provide such code unification. How then one is supposed to go about
> such feature?

You might be interested in Emmanuel's 'traits'-based containers, see
[2], [3].

> On a related note, I was rather surprised that the related types in
> Ada.Containers do not form such a hierarchy. Say both
> Ada.Containers.Vectors and Indefinite_Vectors (and especially now with
> addition of Bounded_Vectors too) all could derive from a common
> ancestor that could be used to implement common functionality and let
> end user chose the desired data storage model..

The Ada 95 Booch Components[4] follow this model. One reason they
weren't taken as a model for Ada.Containers was that the model requires
multiple levels of generic instantiation of child packages: for example,
to make an unbounded map from Unbounded_String to Unbounded_String
requires

   with Ada.Strings.Unbounded;
   with BC.Containers.Maps.Unbounded;
   with BC.Support.Standard_Storage;

   package Configuration_Demo_Support is

      package Abstract_String_Containers is new BC.Containers
        (Item => Ada.Strings.Unbounded.Unbounded_String,
         "=" => Ada.Strings.Unbounded."=");

      package Abstract_String_Maps
      is new Abstract_String_Containers.Maps
        (Key => Ada.Strings.Unbounded.Unbounded_String,
         "=" => Ada.Strings.Unbounded."=");

      function Hash (S : Ada.Strings.Unbounded.Unbounded_String)
        return Natural;

      package String_Maps
      is new Abstract_String_Maps.Unbounded
        (Hash => Hash,
         Buckets => 43,
         Storage => BC.Support.Standard_Storage.Pool);

   end Configuration_Demo_Support;

[1] http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-A-18-2.html#p34.3
[2] https://blog.adacore.com/traits-based-containers
[3] https://github.com/AdaCore/ada-traits-containers
[4] https://sourceforge.net/projects/booch95/


^ permalink raw reply	[relevance 0%]

* Re: class wide iterable (and indexable)
  2019-01-02 17:39  4% ` Simon Wright
@ 2019-01-02 18:11  6%   ` George Shapovalov
  2019-01-03  8:52  0%     ` Simon Wright
  2019-01-03 22:56  0%     ` Randy Brukardt
  0 siblings, 2 replies; 200+ results
From: George Shapovalov @ 2019-01-02 18:11 UTC (permalink / raw)


Thanks!
I'll try adding this and see if I can get around that invalid interface conversion. 

I did see in the Ada.Containers.Vectors code two versions defined, however I was not clear on why, especially since both the Ada Gem 10x (I forgot now exact number) and Ada Rationale for 2012 seem to only provide one, with a Cursor. Besides, that seemed to work just fine when specific types are declared, only class-wide gave me trouble.. 
Interesting that indexing works fine, no confusion here (but of course it goes through other aspects, and there I had to change the name of the referenced function in derived type, otherwise the compiler was getting confused too - I left a comment in the code to this effect)..

However, from your response (also my general impression while digging through the iterables workings) is that this is not a common way to provide such code unification. How then one is supposed to go about such feature? 

On a related note, I was rather surprised that the related types in Ada.Containers do not form such a hierarchy. Say both Ada.Containers.Vectors and Indefinite_Vectors (and especially now with addition of Bounded_Vectors too) all could derive from a common ancestor that could be used to implement common functionality and let end user chose the desired data storage model..

^ permalink raw reply	[relevance 6%]

* Re: class wide iterable (and indexable)
  2019-01-02 15:48  3% class wide iterable (and indexable) George Shapovalov
@ 2019-01-02 17:39  4% ` Simon Wright
  2019-01-02 18:11  6%   ` George Shapovalov
  2019-01-26 22:11  3% ` George Shapovalov
  1 sibling, 1 reply; 200+ results
From: Simon Wright @ 2019-01-02 17:39 UTC (permalink / raw)


George Shapovalov <gshapovalov@gmail.com> writes:

> I would be thankful for any pointers, as I am at a loss what that
> class-wide for loop is getting confused about. Or why it even expects
> the Index type in the "of" loop?

Compiling (a subsection of) your code with -gnatG, which lists the
generated expanded code in an Ada-like syntax, we get

      C2220b : test_list_iface__pl__cursor := T2232b!(
        test_list_iface__pl__list_iterator_interfaces__reversible_iteratorH!
        (I2224b).all (1)).all (I2224b);
      L_5 : while test_list_iface__pl__has_element (C2220b) loop
         n : test_list_iface__pl__element_type renames
           test_list_iface__pl__list_reference (lc, C2220b);
         ada__text_io__put__4 (n'img);
         C2220b :=
           $test_list_iface__pl__list_iterator_interfaces__next__2 (
           I2224b, C2220b);
      end loop L_5;

which shows that part of the code (correctly) expects an integer, while
another part provides a cursor; so you're right, the compiler is
confused, this is a compiler bug.

However, I think the issue may be that you've only defined one function
List_Reference: if you look at Ada.Containers.Vectors you'll see

   function Reference
     (Container : aliased in out Vector;
      Position  : Cursor) return Reference_Type;
   pragma Inline (Reference);
...
   function Reference
     (Container : aliased in out Vector;
      Index     : Index_Type) return Reference_Type;
   pragma Inline (Reference);

so GNAT's "bug" is that it doesn't understand how to cope with your
error. AdaCore are always interested in improving error messages, but
this error does seem rather out of the ordinary!

I had a quick-and-dirty go at fixing this, & got a build, but ended with

testing List_Interface'Class ..
assignin values .. done;  values: 
Catchpoint 1, CONSTRAINT_ERROR (Ada.Tags.Displace: invalid interface conversion) at 0x00000001000210da in test_list_iface.pld.iterate (container=..., 
    <iterateBIPalloc>=2, <iterateBIPstoragepool>=0x0, 
    <iterateBIPfinalizationmaster>=0x0, <iterateBIPaccess>=0x0)
    at /Users/simon/tmp/cla/ada_gems/list_iface/src/lists-dynamic.adb:46
46	        return List_Iterator_Interfaces.Reversible_Iterator'Class(ACV.Vector(Container).Iterate);
(gdb) l
41	--     end;
42	
43	    overriding
44	    function Iterate (Container : in List) return List_Iterator_Interfaces.Reversible_Iterator'Class is
45	    begin
46	        return List_Iterator_Interfaces.Reversible_Iterator'Class(ACV.Vector(Container).Iterate);
47	    end;
48	
49	end Lists.dynamic;

Hope this helps ...


^ permalink raw reply	[relevance 4%]

* class wide iterable (and indexable)
@ 2019-01-02 15:48  3% George Shapovalov
  2019-01-02 17:39  4% ` Simon Wright
  2019-01-26 22:11  3% ` George Shapovalov
  0 siblings, 2 replies; 200+ results
From: George Shapovalov @ 2019-01-02 15:48 UTC (permalink / raw)


Hello,

I apologize if something like this is a common thing, but search here or on google does not turn up much of directly related info, and I cannot quite understand why the following confuses gnat..

The intention here is to create a top-level interface providing iterable/indexable, well, interface, with specific derived types providing appropriate data handling (say to let user select either dynamic, Ada.Containers.Vectors based, or fixed, based on plain arrays storage). 

See here for working code:
https://github.com/gerr135/ada_gems/tree/master/list_iface

So, I would have 
package Lists is ..
type List_Interface is interface
        with Constant_Indexing => List_Constant_Reference,
            Variable_Indexing => List_Reference,
            Default_Iterator  => Iterate,
            Iterator_Element  => Element_Type;

package Lists.Dynamic is ..
type List is new List_Interface with private ..

package Lists.Fixed is ..
type List is new List_Interface with private..

with all appropriate elements declared as abstract and derived types implementing them - either directly attaching Vector interface or wrapping around base array..

Then common code could be kept in class-wide methods, using the new loop forms, like in:
--
for item of List loop
  do_something(item);
end loop;
as well as direct indexing, i.e. List(i)
--
with specific storage types selected as needed in client procedures. In most optimistic scenario only declarative region would need light changes..

This all works well in fact, as long as I operate on specific types. But as soon as I try to use class-wide variable, the "of" form of the loop seems to confuse the compiler.
Thus, e.g. 

LL : Lists.Dynamic.List;
for l of LL loop .. -- works fine

but
LC : Lists.List_Interface'Class := Lists.Dynamic.To_Vector(5);
for l of LC loop .. -- confuses the compiler

And I just cannot see what's so special about this class-wide here. It all seems to follow exactly the same form (by design it passes all compiler checks up to this point).

Please see here for the code:
https://github.com/gerr135/ada_gems/tree/master/list_iface

the specific error is:
test_list_iface.adb:91:17: expected type "Standard.Integer"
test_list_iface.adb:91:17: found private type "Cursor" defined at lists.ads:32, instance at line 22
(and one more line further down that is clearly derivative)

This is not quite a 5-line example code, but implementing iterable/indexable interfaces with proper inheritance is somewhat beasty (even if its utility is in concise end-point code). I am afraid this is the minimal code that would illustrate the point (cut and reformed from larger project where I was trying such approach. Perhaps I should turn to iterating over some index type, which needs to be provided anyway. Seems to be simpler and as readable, but what is there the new interface for, if not to be tried out? :) ).

I would be thankful for any pointers, as I am at a loss what that class-wide for loop is getting confused about. Or why it even expects the Index type in the "of" loop?

Thank you for any pointers.

George

^ permalink raw reply	[relevance 3%]

* Re: Сreate attributes.
  2018-12-22  5:37  5% Сreate attributes eduardsapotski
@ 2018-12-22 19:13  0% ` Brad Moore
  0 siblings, 0 replies; 200+ results
From: Brad Moore @ 2018-12-22 19:13 UTC (permalink / raw)


On Friday, December 21, 2018 at 10:37:14 PM UTC-7, eduards...@gmail.com wrote:
> Sorry for the stupid question...
> 
> For example. I have type:
> 
>    type Person is record
>       First_Name : Unbounded_String := Null_Unbounded_String;
>       Last_Name : Unbounded_String := Null_Unbounded_String;
>    end record;
> 
> There is a list:
> 
>    package People_Package is new  Ada.Containers.Vectors(Natural, Person);
>    People : People_Package.Vector;
> 
> Next, I want to display this list with headers:
> 
> ----------------------------
> |   NAME    |   SURNAME    |
> ----------------------------
> |   John    |    Smith     |
> |   Ada     |   Lovelace   |
> ...
> ----------------------------
> 
> Can I use attributes to display headers?
> For example something like this:
> 
> People'First_Name_Header
> 
> 
> How can this be implemented?

You could use a class-wide type or a type with discriminants such as;

   type Person_Attribute_Kinds is (Name, Surname);
   
   type Person_Attribute (Attribute_Name : Person_Attribute_Kinds
                          := Person_Attribute_Kinds'First) is
      record
         case Attribute_Name is
            when Name | Surname =>
               Name_String : Unbounded_String := Null_Unbounded_String;
         end case;
      end record;
      
      type Person is
         record
            First_Name : Person_Attribute(Name);
            Last_Name  : Person_Attribute(Surname);
         end record;
      
   X : Person;
begin
   Put_Line ("| " & X.First_Name.Attribute_Name'Image &
              " | " & X.Last_Name.Attribute_Name'Image & " |");


^ permalink raw reply	[relevance 0%]

* Сreate attributes.
@ 2018-12-22  5:37  5% eduardsapotski
  2018-12-22 19:13  0% ` Brad Moore
  0 siblings, 1 reply; 200+ results
From: eduardsapotski @ 2018-12-22  5:37 UTC (permalink / raw)


Sorry for the stupid question...

For example. I have type:

   type Person is record
      First_Name : Unbounded_String := Null_Unbounded_String;
      Last_Name : Unbounded_String := Null_Unbounded_String;
   end record;

There is a list:

   package People_Package is new  Ada.Containers.Vectors(Natural, Person);
   People : People_Package.Vector;

Next, I want to display this list with headers:

----------------------------
|   NAME    |   SURNAME    |
----------------------------
|   John    |    Smith     |
|   Ada     |   Lovelace   |
...
----------------------------

Can I use attributes to display headers?
For example something like this:

People'First_Name_Header


How can this be implemented?

^ permalink raw reply	[relevance 5%]

* Re: GNATCOLL JSON Parsing
  2018-06-08  5:52  5% GNATCOLL JSON Parsing eduardsapotski
  2018-06-08  9:35  0% ` Björn Lundin
@ 2018-06-08 12:00  0% ` Per Sandberg
  1 sibling, 0 replies; 200+ results
From: Per Sandberg @ 2018-06-08 12:00 UTC (permalink / raw)


On Friday, June 8, 2018 at 7:52:56 AM UTC+2, eduards...@gmail.com wrote:
> I try understand parsing JSON in Ada. 
> 
> For example:
> Have web-api that gives simple JSON: http://api.exmo.com/v1/trades/?pair=BTC_USD&limit=10
> 
> I need to save this data to database.
> Created type:
> 
>    type Money is delta 0.00000001 range 0.0 .. 9_999_999_999.9;
>    type UTC_Date is range 1_500_000_000 .. 3_000_000_000;
> 
>    type Trade is record
> 
>       Trade_Id   : Integer;
>       Pair       : Unbounded_String;
>       Trade_Type : Unbounded_String;
>       Price      : Money;
>       Quantity   : Money;
>       Amount     : Money;
>       Date       : UTC_Date;
>       Saved      : Boolean;
> 
>    end record;
> 
> Created collection:
> 
>     package Vector_Trades is new Ada.Containers.Vectors(Natural, Trade);
> 
>     Trades : Vector_Trades.Vector;
> 
> Receive data:
> 
> JSON : Unbounded_String;
> 
> JSON := To_Unbounded_String(AWS.Response.Message_Body (AWS.Client.Get (URL => "http://api.exmo.com/v1/trades/?pair=BTC_USD&limit=10")));
> 
> What to do next? How to get list of objects from the JSON-text?
> 
> How to save data to database already understood.
> 
> Thanks.

You might find the library
 https://github.com/persan/gnatcoll-json
Usefull it contains JSON suport for most Ada.Containers.* packages and som examples.
/P

^ permalink raw reply	[relevance 0%]

* Re: GNATCOLL JSON Parsing
  2018-06-08  5:52  5% GNATCOLL JSON Parsing eduardsapotski
@ 2018-06-08  9:35  0% ` Björn Lundin
  2018-06-08 12:00  0% ` Per Sandberg
  1 sibling, 0 replies; 200+ results
From: Björn Lundin @ 2018-06-08  9:35 UTC (permalink / raw)


On 2018-06-08 07:52, eduardsapotski@gmail.com wrote:
> I try understand parsing JSON in Ada. 
> 
> For example:
> Have web-api that gives simple JSON: http://api.exmo.com/v1/trades/?pair=BTC_USD&limit=10
> 
> I need to save this data to database.
> Created type:
> 
>    type Money is delta 0.00000001 range 0.0 .. 9_999_999_999.9;
>    type UTC_Date is range 1_500_000_000 .. 3_000_000_000;
> 
>    type Trade is record
> 
>       Trade_Id   : Integer;
>       Pair       : Unbounded_String;
>       Trade_Type : Unbounded_String;
>       Price      : Money;
>       Quantity   : Money;
>       Amount     : Money;
>       Date       : UTC_Date;
>       Saved      : Boolean;
> 
>    end record;
> 
> Created collection:
> 
>     package Vector_Trades is new Ada.Containers.Vectors(Natural, Trade);
> 
>     Trades : Vector_Trades.Vector;
> 
> Receive data:
> 
> JSON : Unbounded_String;
> 
> JSON := To_Unbounded_String(AWS.Response.Message_Body (AWS.Client.Get (URL => "http://api.exmo.com/v1/trades/?pair=BTC_USD&limit=10")));
> 
> What to do next? How to get list of objects from the JSON-text?


something like (not tested):
declare
   use gnatcoll.Json;
   current_item, Reply : JSON_Value := Create;
   BTC_Array : json_array := empty_array;
begin
  Reply := Read(Strm => Aws.Response.Message_Body(AWS_Reply),Filename =>
"");

  if reply.has_Field("BTC_USD") then
     btc_array := reply.Get("BTC_USD");
     if length(btc_array) > 0 then
        for i in 1 .. length(btc_array) loop
           Current_Item := Get(btc_array, i);
           declare
             tradeid : integer := 0;
           begin
             if Current_item.Has_Field("tradeid") then
               tradeid := current_item.Get(""tradeid);
             end if;
               ...
           end;
        end loop;
     end if;
  end if;
end;





> 
> How to save data to database already understood.
> 
> Thanks.
> 
> 
> 
> 
> 
> 


-- 
--
Björn

^ permalink raw reply	[relevance 0%]

* GNATCOLL JSON Parsing
@ 2018-06-08  5:52  5% eduardsapotski
  2018-06-08  9:35  0% ` Björn Lundin
  2018-06-08 12:00  0% ` Per Sandberg
  0 siblings, 2 replies; 200+ results
From: eduardsapotski @ 2018-06-08  5:52 UTC (permalink / raw)


I try understand parsing JSON in Ada. 

For example:
Have web-api that gives simple JSON: http://api.exmo.com/v1/trades/?pair=BTC_USD&limit=10

I need to save this data to database.
Created type:

   type Money is delta 0.00000001 range 0.0 .. 9_999_999_999.9;
   type UTC_Date is range 1_500_000_000 .. 3_000_000_000;

   type Trade is record

      Trade_Id   : Integer;
      Pair       : Unbounded_String;
      Trade_Type : Unbounded_String;
      Price      : Money;
      Quantity   : Money;
      Amount     : Money;
      Date       : UTC_Date;
      Saved      : Boolean;

   end record;

Created collection:

    package Vector_Trades is new Ada.Containers.Vectors(Natural, Trade);

    Trades : Vector_Trades.Vector;

Receive data:

JSON : Unbounded_String;

JSON := To_Unbounded_String(AWS.Response.Message_Body (AWS.Client.Get (URL => "http://api.exmo.com/v1/trades/?pair=BTC_USD&limit=10")));

What to do next? How to get list of objects from the JSON-text?

How to save data to database already understood.

Thanks.







^ permalink raw reply	[relevance 5%]

* Re: Memory pools
    2018-05-31 19:28  5% ` gorgelo
@ 2018-05-31 19:33  5% ` gorgelo
  1 sibling, 0 replies; 200+ results
From: gorgelo @ 2018-05-31 19:33 UTC (permalink / raw)


And to follow up on the naive benchmarks:
https://github.com/frol/completely-unscientific-benchmarks

Using the memory pool in the previous post it can be used to implement the Treap algorithm (after some minor modifications):

pragma Suppress (Tampering_Check);
-- Tampering checks are only for multi-task applications.
-- Since this application is single task we can safely
-- suppress tampering checks of the standard containers.
-- If performance is an issue, the Ada-Traits Containers may be used instead.

with System.Storage_Elements;
with System.Storage_Pools;
with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Containers.Vectors;
with Ada.Unchecked_Deallocation;
with Ada.Numerics.Discrete_Random;

procedure Main is

   subtype Storage_Offset is System.Storage_Elements.Storage_Offset;
   subtype Storage_Count  is System.Storage_Elements.Storage_Count;
   subtype Storage_Array  is System.Storage_Elements.Storage_Array;

   subtype Root_Storage_Pool is System.Storage_Pools.Root_Storage_Pool;

   subtype Integer_Address is System.Storage_Elements.Integer_Address;

   subtype Count_Type is Ada.Containers.Count_Type;

   use type Count_Type;
   use type Storage_Offset;
   use type Integer_Address;

   procedure Put (Text : String) renames Ada.Text_IO.Put;

   procedure Put_Line (Text : String) renames Ada.Text_IO.Put_Line;

   procedure Put_Line (I : Integer) is
   begin
      Ada.Integer_Text_IO.Put (I, 0);
      Ada.Text_IO.New_Line;
   end Put_Line;

   procedure Put (I : Integer) is
   begin
      Ada.Integer_Text_IO.Put (I, 0);
   end Put;

   procedure Put (I : Storage_Offset) is
   begin
      Ada.Integer_Text_IO.Put (Integer (I), 0);
   end Put;

   function To_Integer (Value : System.Address) return Integer_Address
                        renames System.Storage_Elements.To_Integer;

   generic
      Slot_Size : Positive;
      -- Specifies the size of each slot in Storage Elements (bytes)
      -- Must be big enough to store any object one wishes to allocate
      -- inside the memory pool.

      MAX : Positive;
      -- Specifies the number of slots that will be allocated in an array
      -- from the heap every time more memory needs to be pre-allocated.

   package Arena_Pools is

      type Arena (<>) is new Root_Storage_Pool with private;

      function Make return Arena;

      overriding
      procedure Allocate
        (  Pool      : in out Arena;
           Address   : out System.Address;
           Size      : Storage_Count;
           Alignment : Storage_Count
          );

      overriding
      procedure Deallocate
        (  Pool      : in out Arena;
           Address   : System.Address;
           Size      : Storage_Count;
           Alignment : Storage_Count
          );

      overriding
      function Storage_Size (Pool : Arena) return Storage_Count;
      -- Approximation of how many Storage Elements (bytes)
      -- have been heap-allocated.

   private

      type Slot is record
         Elements : Storage_Array (1..Storage_Offset (Slot_Size));
      end record;

      subtype Slot_Index is Storage_Offset range 1.. Storage_Offset (MAX);

      type Slots_Array is array (Slot_Index) of Slot;

      subtype Free_Index is Integer range 1..MAX;
      -- This Integer type (32-bits) is created in order to not use the type
      -- Storage_Offset (64-bits) in the free indices vector.

      package Indices_Vector is new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Free_Index,
         "="          => "=");

      type Slots_Envelope is record
         Items        : Slots_Array;
         Free_Indices : Indices_Vector.Vector;
      end record;

      type Slots_Envelope_Ptr is access all Slots_Envelope;

      package Envelope_Vectors is new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Slots_Envelope_Ptr,
         "="          => "=");

      type Arena is new Root_Storage_Pool with record
         Index : Positive := 1;
         -- Indicates which array of slots to first search for a free index

         Envelopes : Envelope_Vectors.Vector;
      end record;

      overriding
      procedure Finalize (This : in out Arena);
      -- Deallocates all allocated memory from the heap

   end Arena_Pools;

   package body Arena_Pools is

      function Make return Slots_Envelope_Ptr is
         Envelope : Slots_Envelope_Ptr := new Slots_Envelope;
      begin
         Envelope.Free_Indices.Reserve_Capacity (Ada.Containers.Count_Type (MAX));
         for I in Slot_Index'Range loop
            Envelope.Free_Indices.Append (Free_Index (I));
         end loop;

         return Envelope;
      end Make;

      function Make return Arena is
         Envelope : Slots_Envelope_Ptr := Make;
      begin
         return This : Arena do
            This.Envelopes.Append (Envelope);
         end return;
      end Make;

      function Determine_Index (Pool    : Arena;
                                Address : System.Address) return Positive is
         Searched_For : Natural := 0;
         First_Address : System.Address;
         Last_Address  : System.Address;
      begin
         for I in Pool.Envelopes.First_Index..Pool.Envelopes.Last_Index loop
            First_Address := Pool.Envelopes (I).Items (1)'Address;
            Last_Address  := Pool.Envelopes (I).Items (Storage_Offset (MAX))'Address;
            if
              To_Integer (First_Address) <= To_Integer (Address) and
              To_Integer (Address)       <= To_Integer (Last_Address)
            then
               Searched_For := I;
               exit;
            end if;
         end loop;

         if Searched_For = 0 then
            raise Storage_Error;
         end if;

         return Searched_For;
      end Determine_Index;

      procedure Allocate
        (Pool      : in out Arena;
         Address   : out System.Address;
         Size      : Storage_Count;
         Alignment : Storage_Count)
      is
         Id : Slot_Index;
      begin
         if Pool.Envelopes (Pool.Index).Free_Indices.Length > 0 then
            Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
            Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
         else
            declare
               Has_Found : Boolean := False;
            begin
               for I in Pool.Envelopes.First_Index .. Pool.Envelopes.Last_Index loop
                  if Pool.Envelopes (I).Free_Indices.Length > 0 then
                     Pool.Index := I;
                     Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
                     Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
                     Has_Found := True;
                     exit;
                  end if;
               end loop;

               if not Has_Found then
                  declare
                     E : Slots_Envelope_Ptr := Make;
                  begin
                     Pool.Envelopes.Append (E);
                     Pool.Index := Pool.Envelopes.Last_Index;
                     Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
                     Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
                  end;
               end if;
            end;
         end if;

         Address := Pool.Envelopes (Pool.Index).Items (Id).Elements'Address;
      end Allocate;

      procedure Deallocate (Pool      : in out Arena;
                            Address   : System.Address;
                            Size      : Storage_Count;
                            Alignment : Storage_Count)
      is
         I : constant Positive := Determine_Index (Pool, Address);

         First_Address : System.Address;
         Last_Address  : System.Address;

         Slot_Id : Slot_Index;

         D : Integer_Address;
      begin
         First_Address := Pool.Envelopes (I).Items (1)'Address;
         Last_Address  := Pool.Envelopes (I).Items (Storage_Offset (MAX))'Address;

         D := (To_Integer (Last_Address) - To_Integer (First_Address) + Integer_Address (Slot_Size)) / Integer_Address (MAX);

         Slot_Id := Slot_Index ((To_Integer (Address) + Integer_Address (Slot_Size) - To_Integer (First_Address))/ D);

         Pool.Envelopes (I).Free_Indices.Append (Free_Index (Slot_Id));
      end Deallocate;

      function Storage_Size (Pool : Arena) return Storage_Count is
         Result : Storage_Count := 0;
      begin
         for Envelope of Pool.Envelopes loop
            Result := Storage_Count (Slot_Size*MAX) + Storage_Count (Envelope.Free_Indices.Capacity * 4);
         end loop;

         return Result;
      end Storage_Size;

      procedure Free is new Ada.Unchecked_Deallocation (Object => Slots_Envelope,
                                                        Name   => Slots_Envelope_Ptr);

      procedure Finalize (This : in out Arena) is
      begin
         for Envelope of This.Envelopes loop
            Free (Envelope);
         end loop;
         This.Envelopes.Clear;
      end Finalize;

   end Arena_Pools;

   package Pools is new Arena_Pools (24, 200_000);

   Pool : Pools.Arena := Pools.Make;

   -- Here ends the definition of the Storage pool and here begins
   -- implementation of the algorithm.

   package Integer_Random is new Ada.Numerics.Discrete_Random (Integer);

   G : Integer_Random.Generator;

   type Node;
   type Node_Ptr is access all Node with
     Storage_Pool => Pool;

   type Node is record
      Left  : Node_Ptr;
      Right : Node_Ptr;
      X     : Integer := 0;
      Y     : Integer := Integer_Random.Random (G);
   end record with
     Size => 24*8;

   package Tree_Def is

      type Tree is tagged private;

      function Has_Value (T : in out Tree;
                          X : in     Integer) return Boolean;

      procedure Insert (T : in out Tree;
                        X : in     Integer);

      procedure Erase (T : in out Tree;
                       X : in     Integer);

   private

      function Merge (Lower   : Node_Ptr;
                      Greater : Node_Ptr) return Node_Ptr;

      function Merge (Lower   : Node_Ptr;
                      Equal   : Node_Ptr;
                      Greater : Node_Ptr) return Node_Ptr;

      procedure Split (Orig             : in     Node_Ptr;
                       Lower            : in out Node_Ptr;
                       Greater_Or_Equal : in out Node_Ptr;
                       Value            : in     Integer);

      procedure Split (Orig    : in     Node_Ptr;
                       Lower   : in out Node_Ptr;
                       Equal   : in out Node_Ptr;
                       Greater : in out Node_Ptr;
                       Value   : in     Integer);

      procedure Make_Node (Node :    out Node_Ptr;
                           X    : in     Integer);

      type Tree is tagged record
         Root: Node_Ptr := null;
      end record;

   end Tree_Def;

   package body Tree_Def is

      procedure Free is new Ada.Unchecked_Deallocation(Object => Node,
                                                       Name   => Node_Ptr);

      procedure Make_Node (Node :    out Node_Ptr;
                           X    : in     Integer) is
      begin
         Node := new Main.Node;
         Node.X := X;
         Node.Y := Integer_Random.Random (G);
      end Make_Node;

      procedure Delete_Node (Node : in out Node_Ptr) is
      begin
         if Node /= null then
            if Node.Left /= null then
               Delete_Node(Node.Left);
            end if;

            if Node.Right /= null then
               Delete_Node (Node.Right);
            end if;

            Free (Node);
         end if;
      end Delete_Node;

      function Merge (Lower   : Node_Ptr;
                      Greater : Node_Ptr) return Node_Ptr is
      begin
         if Lower = null then
            return Greater;
         end if;

         if Greater = null then
            return lower;
         end if;

         if Lower.Y < Greater.Y then
            Lower.Right := Merge (Lower.Right, Greater);
            return Lower;
         else
            Greater.Left := Merge (Lower, Greater.Left);
            return Greater;
         end if;
      end Merge;

      function Merge (Lower   : Node_Ptr;
                      Equal   : Node_Ptr;
                      Greater : Node_Ptr) return Node_Ptr is
      begin
         return Merge (Merge (Lower, Equal), Greater);
      end merge;

      procedure Split (Orig             : in     Node_Ptr;
                       Lower            : in out Node_Ptr;
                       Greater_Or_Equal : in out Node_Ptr;
                       Value            : in     Integer) is
      begin
         if Orig = null then
            Lower := null;
            Greater_Or_Equal := null;
            return;
         end if;
         if Orig.X < Value then
            Lower := Orig;
            Split (Lower.Right, Lower.Right, Greater_Or_Equal, Value);
         else
            Greater_Or_Equal := Orig;
            Split (Greater_Or_Equal.Left, Lower, Greater_Or_Equal.Left, Value);
         end if;
      end Split;

      procedure Split (Orig    : in     Node_Ptr;
                       Lower   : in out Node_Ptr;
                       Equal   : in out Node_Ptr;
                       Greater : in out Node_Ptr;
                       Value   : in     Integer)
      is
         Equal_Or_Greater: Node_Ptr;
      begin
         Split (Orig, Lower, Equal_Or_Greater, Value);
         Split (Equal_Or_Greater, Equal, Greater, Value + 1);
      end Split;

      function Has_Value (T : in out Tree;
                          X : in     Integer) return Boolean
      is
         Lower   : Node_Ptr;
         Equal   : Node_Ptr;
         Greater : Node_Ptr;

         Result : Boolean;
      begin
         Split (T.Root, Lower, Equal, Greater, X);
         Result := Equal /= null;
         T.Root := Merge (Lower, Equal, Greater);
         return Result;
      end Has_Value;

      procedure Insert (T : in out Tree;
                        X : in     Integer)
      is
         Lower   : Node_Ptr;
         Equal   : Node_Ptr;
         Greater : Node_Ptr;
      begin
         Split (T.Root, Lower, Equal, Greater, X);
         if Equal = null then
            Make_Node (Equal, X);
         end if;
         T.Root := Merge (Lower, Equal, Greater);
      end Insert;

      procedure Erase (T : in out Tree;
                       X : in     Integer) is
         Lower   : Node_Ptr;
         Equal   : Node_Ptr;
         Greater : Node_Ptr;
      begin
         Split (T.Root, Lower, Equal, Greater, X);
         T.Root := Merge (Lower, Greater);
         -- commenting out the following line
         -- doesn't seem to affect running time by much, if at all
         Delete_Node (Equal);
      end Erase;

   end Tree_Def;

   Tree    : Tree_Def.Tree;
   Current : Integer := 5;
   Result  : Integer := 0;
   Mode    : Integer;

begin
   Integer_Random.Reset (G);

   for I in 1..1_000_000 loop
      Mode := I mod 3;
      Current := (Current * 57 + 43) mod 10007;
      if Mode = 0 then
         Tree.Insert (Current);
      elsif Mode = 1 then
         Tree.Erase (Current);
      else
         Result := Result + (if Tree.Has_Value (Current) then 1 else 0);
      end if;
   end loop;
   Put_Line (Result);

end Main;

^ permalink raw reply	[relevance 5%]

* Re: Memory pools
  @ 2018-05-31 19:28  5% ` gorgelo
  2018-05-31 19:33  5% ` gorgelo
  1 sibling, 0 replies; 200+ results
From: gorgelo @ 2018-05-31 19:28 UTC (permalink / raw)


Here is an example of an unbounded storage pool that handles deallocations and is used for allocating 3 Integers inside it and then deallocating them:

with System.Storage_Elements;
with System.Storage_Pools;
with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Containers.Vectors;
with Ada.Unchecked_Deallocation;

procedure Main is

   subtype Storage_Offset is System.Storage_Elements.Storage_Offset;
   subtype Storage_Count  is System.Storage_Elements.Storage_Count;
   subtype Storage_Array  is System.Storage_Elements.Storage_Array;

   subtype Root_Storage_Pool is System.Storage_Pools.Root_Storage_Pool;

   subtype Integer_Address is System.Storage_Elements.Integer_Address;

   use type Ada.Containers.Count_Type;
   use type Storage_Offset;
   use type Integer_Address;

   procedure Put (Text : String) renames Ada.Text_IO.Put;

   procedure Put_Line (Text : String) renames Ada.Text_IO.Put_Line;

   procedure Put_Line (I : Integer) is
   begin
      Ada.Integer_Text_IO.Put (I);
      Ada.Text_IO.New_Line;
   end Put_Line;

   procedure Put (I : Integer) is
   begin
      Ada.Integer_Text_IO.Put (I, 0);
   end Put;

   procedure Put (I : Storage_Offset) is
   begin
      Ada.Integer_Text_IO.Put (Integer (I), 0);
   end Put;

   function To_Integer (Value : System.Address) return Integer_Address
                        renames System.Storage_Elements.To_Integer;

   package Arena_Pools is

      type Arena (<>) is new Root_Storage_Pool with private;

      function Make return Arena;

      overriding
      procedure Allocate
        (  Pool      : in out Arena;
           Address   : out System.Address;
           Size      : Storage_Count;
           Alignment : Storage_Count
          );

      overriding
      procedure Deallocate
        (  Pool      : in out Arena;
           Address   : System.Address;
           Size      : Storage_Count;
           Alignment : Storage_Count
          );

      overriding
      function Storage_Size (Pool : Arena) return Storage_Count;
      -- Approximation of how many Storage Elements (bytes)
      -- have been heap-allocated.

   private

      Slot_Size : constant := 20;
      -- Specifies the size of each slot in Storage Elements (bytes)
      -- Must be big enough to store any object one wishes to allocate
      -- inside the memory pool.

      type Slot is record
         Elements : Storage_Array (1..Slot_Size);
      end record;

      MAX : constant := 200_000;
      -- Specifies the number of slots that will be allocated in an array
      -- from the heap every time more memory needs to be pre-allocated.

      subtype Slot_Index is Storage_Offset range 1..MAX;

      type Slots_Array is array (Slot_Index) of Slot;

      subtype Free_Index is Integer range 1..MAX;
      -- This Integer type (32-bits) is created in order to not use the type
      -- Storage_Offset (64-bits) in the free indices vector.

      package Indices_Vector is new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Free_Index,
         "="          => "=");

      type Slots_Envelope is record
         Items        : Slots_Array;
         Free_Indices : Indices_Vector.Vector;
      end record;

      type Slots_Envelope_Ptr is access all Slots_Envelope;

      package Envelope_Vectors is new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Slots_Envelope_Ptr,
         "="          => "=");

      type Arena is new Root_Storage_Pool with record
         Index : Positive := 1;
         -- Indicates which array of slots to first search for a free index

         Envelopes : Envelope_Vectors.Vector;
      end record;

      overriding
      procedure Finalize (This : in out Arena);
      -- Deallocates all allocated memory from the heap

   end Arena_Pools;

   package body Arena_Pools is

      function Make return Slots_Envelope_Ptr is
         Envelope : Slots_Envelope_Ptr := new Slots_Envelope;
      begin
         Envelope.Free_Indices.Reserve_Capacity (MAX);
         for I in Slot_Index'Range loop
            Envelope.Free_Indices.Append (Free_Index (I));
         end loop;

         return Envelope;
      end Make;

      function Make return Arena is
         Envelope : Slots_Envelope_Ptr := Make;
      begin
         return This : Arena do
            This.Envelopes.Append (Envelope);
         end return;
      end Make;

      function Determine_Index (Pool    : Arena;
                                Address : System.Address) return Positive is
         Searched_For : Natural := 0;
         First_Address : System.Address;
         Last_Address  : System.Address;
      begin
         for I in Pool.Envelopes.First_Index..Pool.Envelopes.Last_Index loop
            First_Address := Pool.Envelopes (I).Items (1)'Address;
            Last_Address  := Pool.Envelopes (I).Items (MAX)'Address;
            if
              To_Integer (First_Address) <= To_Integer (Address) and
              To_Integer (Address)       <= To_Integer (Last_Address)
            then
               Searched_For := I;
               exit;
            end if;
         end loop;

         if Searched_For = 0 then
            raise Storage_Error;
         end if;

         return Searched_For;
      end Determine_Index;

      procedure Allocate
        (Pool      : in out Arena;
         Address   : out System.Address;
         Size      : Storage_Count;
         Alignment : Storage_Count)
      is
         Id : Slot_Index;
      begin
         if Pool.Envelopes (Pool.Index).Free_Indices.Length > 0 then
            Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
            Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
         else
            declare
               Has_Found : Boolean := False;
            begin
               for I in Pool.Envelopes.First_Index .. Pool.Envelopes.Last_Index loop
                  if Pool.Envelopes (I).Free_Indices.Length > 0 then
                     Pool.Index := I;
                     Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
                     Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
                     Has_Found := True;
                     exit;
                  end if;
               end loop;

               if not Has_Found then
                  declare
                     E : Slots_Envelope_Ptr := Make;
                  begin
                     Pool.Envelopes.Append (E);
                     Pool.Index := Pool.Envelopes.Last_Index;
                     Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
                     Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
                  end;
               end if;
            end;
         end if;

         Put ("Will allocate (array, slot) := (");
         Put (Pool.Index);
         Put (",");
         Put (Id);
         Put_Line (")");

         Address := Pool.Envelopes (Pool.Index).Items (Id).Elements'Address;
      end Allocate;

      procedure Deallocate (Pool      : in out Arena;
                            Address   : System.Address;
                            Size      : Storage_Count;
                            Alignment : Storage_Count)
      is
         I : constant Positive := Determine_Index (Pool, Address);

         First_Address : System.Address;
         Last_Address  : System.Address;

         Slot_Id : Slot_Index;

         D : Integer_Address;
      begin
         First_Address := Pool.Envelopes (I).Items (1)'Address;
         Last_Address  := Pool.Envelopes (I).Items (MAX)'Address;

         D := (To_Integer (Last_Address) - To_Integer (First_Address) + Slot_Size) / MAX;

         Slot_Id := Slot_Index ((To_Integer (Address) + Slot_Size - To_Integer (First_Address))/ D);

         Pool.Envelopes (I).Free_Indices.Append (Free_Index (Slot_Id));

         Put ("Deallocate (array, slot) := (");
         Put (I);
         Put (",");
         Put (Slot_Id);
         Put_Line (")");
      end Deallocate;

      function Storage_Size (Pool : Arena) return Storage_Count is
         Result : Storage_Count := 0;
      begin
         for Envelope of Pool.Envelopes loop
            Result := Slot_Size*MAX + Storage_Count (Envelope.Free_Indices.Capacity * 4);
         end loop;

         return Result;
      end Storage_Size;

      procedure Free is new Ada.Unchecked_Deallocation (Object => Slots_Envelope,
                                                        Name   => Slots_Envelope_Ptr);

      procedure Finalize (This : in out Arena) is
      begin
         for Envelope of This.Envelopes loop
            Free (Envelope);
         end loop;
         This.Envelopes.Clear;
         Put_Line ("Deallocated all heap-allocated memory");
      end Finalize;

   end Arena_Pools;

   Pool : Arena_Pools.Arena := Arena_Pools.Make;

   type Integer_Ptr is access Integer with
     Storage_Pool => Pool;

   procedure Free is new Ada.Unchecked_Deallocation (Object => Integer,
                                                     Name   => Integer_Ptr);

   X : Integer_Ptr := new Integer'(1);
   Y : Integer_Ptr := new Integer'(2);
   Z : Integer_Ptr := new Integer'(3);

begin
   Free (X);
   Free (Y);
   Free (Z);
   Put_Line ("Has allocated" & Pool.Storage_Size'Image & " bytes.");
end Main;

It has the following output:
Will allocate (array, slot) := (1,200000)
Will allocate (array, slot) := (1,199999)
Will allocate (array, slot) := (1,199998)
Deallocate (array, slot) := (1,200000)
Deallocate (array, slot) := (1,199999)
Deallocate (array, slot) := (1,199998)
Has allocated 4800000 bytes.
Deallocated all heap-allocated memory


The implementation is inspired from Rosetta stone Arena pools:
http://rosettacode.org/wiki/Arena_storage_pool#Ada

^ permalink raw reply	[relevance 5%]

* Re: How to get Ada to “cross the chasm”?
  @ 2018-05-04 19:05  5%   ` Jere
  0 siblings, 0 replies; 200+ results
From: Jere @ 2018-05-04 19:05 UTC (permalink / raw)


On Friday, May 4, 2018 at 12:13:09 PM UTC-4, guyclaud wrote:
> Since this topic has somewhat turn into a Ada vs Rust/Haskell/whatever, could some experts show a piece of Ada code where the "borrower-checker" would more check/security ? Or are the paradigms too different to show a snippet close enough to (or IN ) Ada so that I can understand ?

They are very different languages.  I am going to try and show a couple of
situations caught by Rust at compile time.  They won't be perfect comparisons
though.  Keep in mind that Ada can pass objects by reference internally 
while in Rust it has to be explicitly requested.  

1.  Dangling references:  Keeping a reference to an object past its lifetime

Ada:
***********************************************
with Ada.Text_IO; use Ada.Text_IO;

procedure jdoodle is
    type Integer_Access is access all Integer;
    
    function Inner(Value : aliased in out Integer) return Integer_Access is
    begin
        return Value'Access;
    end Inner;
    
    function Outer return Integer_Access is
        Value : aliased Integer := 0;
    begin
        return Inner(Value);
    end Outer;
    
    Ptr : Integer_Access := Outer;  -- !!! Dangling reference
begin
    Put_Line("Hello World");
end jdoodle;
***********************************************
Hello World

gcc -c jdoodle.adb
gnatbind -x jdoodle.ali
gnatlink jdoodle.ali -o jdoodle



A attempt to the equivalent in Rust:
***********************************************
pub fn Inner(value : & mut i32) -> & mut i32 {
    return value;
}

pub fn Outer() -> &mut i32 {
    let mut x = 0 as i32;
    return Inner(&x);
}

pub fn main() {
    let ptr : &mut i32 = Outer;
    println!("Hello World")
}
***********************************************
Compiling playground v0.0.1 (file:///playground)
error[E0106]: missing lifetime specifier
 --> src/main.rs:5:19
  |
5 | pub fn Outer() -> &mut i32 {
  |                   ^ expected lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
  = help: consider giving it a 'static lifetime

You have to make it use a static lifetime to work (which removes the
dangling reference) while Ada does accept it as is.


2.  Concurrent Erroneous Access
Ada:
******************************************
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;

procedure jdoodle is

    package Vectors is new Ada.Containers.Vectors(Positive,Integer);

    type Some_Type is limited record
        Data : Vectors.Vector;
    end record;
    
    Some_Object : aliased Some_Type;
    
    task Some_Task is
        entry Start;
    end Some_Task;
    
    task body Some_Task is
    begin
        accept Start;
        for Index in 1 .. 100 loop
            Some_Object.Data.Append(Index);
        end loop;
    end Some_Task;
    
begin
    Put_Line("Hello World");
    Some_Task.Start;
    for Index in 1 .. 100 loop
        Some_Object.Data.Append(Index);  -- !!! Possible Erroneous Memory Access
    end loop;
end jdoodle;
******************************************
Hello World

gcc -c jdoodle.adb
gnatbind -x jdoodle.ali
gnatlink jdoodle.ali -o jdoodle



Attempt at a similar setup in Rust:
******************************************
use std::vec;
use std::thread;

pub struct SomeType {
    pub data : vec::Vec<i32>
}

pub fn main() {
    let mut some_object = SomeType{
        data : vec::Vec::new()
    };
    
    println!("Hello World");
    
    let handler = thread::spawn(move || {
        for index in 1 .. 11 {
            some_object.data.push(index as i32);
        }
    });
    
    for index in 1 .. 11 {
        some_object.data.push(index as i32);
    }
    handler.join().unwrap();
}
******************************************
Compiling playground v0.0.1 (file:///playground)
error[E0382]: use of moved value: `some_object.data`
  --> src/main.rs:22:9
   |
15 |     let handler = thread::spawn(move || {
   |                                 ------- value moved (into closure) here
...
22 |         some_object.data.push(index as i32);
   |         ^^^^^^^^^^^^^^^^ value used here after move
   |
   = note: move occurs because `some_object` has type `SomeType`, which does not implement the `Copy` trait

If you try and remove the move specifier it then gives the error
that you need to put the move specifier to pass data into the thread.
Basically, in Rust it forces you to use synchronization primitives
on any variable being used in a thread (task equiv), which would be
similar to if Ada required all variables in a thread to be protected
types or fulfilled some other task safe context.

Again, the languages are quite different so it is really hard to 
put together an actual comparison.  Ada has many strengths over
Rust though.  It is always easy to find some area where language
x is better than langauge y in a particular area.  What matters
most is the whole package vs the whole package and how they affect
software development and design.


^ permalink raw reply	[relevance 5%]

* Possible GNAT bug, but wanted to see if it was a violtion of the RM
@ 2018-02-23  2:36  7% Jere
  0 siblings, 0 replies; 200+ results
From: Jere @ 2018-02-23  2:36 UTC (permalink / raw)


It took a while, but I got a small contrived example to get this bug.
The gist:

Windows 10
GNAT GPL 2017
FSF GNAT 7.2 hosted on mingw64 for x86_64

I was working on some code that used composition to build up some
components.  I was adding iteration to the top level component using
an internal component as the basis for it.  I started running into
runtime error when I did a "for E of Container loop" construct.  The
exceptions happened at the end of the program and raised Program_Error
mentioning an exception in Finalize/Adjust.  Below is a very contrived
example, but I wanted a minimal compilable example to provide.

I'm certain there is a GNAT bug here, as merely changing how I call a
function (changing from object.function to package.function(object)),
removes the runtime error.  On the flip side, I am using anonymous
access types (as required for the indexing operations), so I might
be misusing those accidentally.  My question is if this is legal
code (and a bug) or not.  I don't know anonymous access types well 
enough to know for sure.

**********************************************************************
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;

procedure Main is

   package Composite is
      
      package Vectors is new Ada.Containers.Vectors(Positive,Integer);
      
      type Instance is tagged limited record
         Vector : Vectors.Vector;
      end record
         with
            Default_Iterator  => Iterate,
            Constant_Indexing => Constant_Reference,
            Iterator_Element  => Integer;
      
      type Constant_Reference_Type
         (Element : not null access constant Integer)
      is limited null record
         with Implicit_Dereference => Element;
      
      function Constant_Reference
         (Container : aliased Instance;
          Cursor    : Vectors.Cursor)
          return Constant_Reference_Type
      -- This version causes a runtime error:
      -- raised PROGRAM_ERROR : main.adb:4 finalize/adjust raised exception
      is (Element =>
             Container.Vector.Constant_Reference(Cursor).Element);
--        -- This version works and does not causes a runtime error
--        is (Element =>
--               Vectors.Constant_Reference(Container.Vector,Cursor).Element);
      
      
      function Iterate
         (Container : Instance)
          return Vectors.Vector_Iterator_Interfaces.Reversible_Iterator'Class
      is (Container.Vector.Iterate);
      
   end Composite;
  
   Container : Composite.Instance;
   
begin
   
   for I in 1..5 loop
      Container.Vector.Append(I);
   end loop;
   
   for E of Container loop
      Put_Line(Integer'Image(E));
   end loop;

end Main;

**********************************************************************

Output:
main.exe
 1
 2
 3
 4
 5

raised PROGRAM_ERROR : main.adb:4 finalize/adjust raised exception
[2018-02-22 21:25:48] process exited with status 1, elapsed time: 00.20s


^ permalink raw reply	[relevance 7%]

* Re: Is Ada.Containers.Vectors.Reference_Type a constrained view?
  2017-10-28 11:10 11% Is Ada.Containers.Vectors.Reference_Type a constrained view? Stephen Leake
@ 2017-11-15  0:38  5% ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2017-11-15  0:38 UTC (permalink / raw)


"Stephen Leake" <stephen_leake@stephe-leake.org> wrote in message 
news:fad2c15c-52e5-416a-b133-a3674afc318c@googlegroups.com...
>I have the following vector type:
>
>   type Indent_Labels is (Not_Set, Int, Anchor, Anchored, Nested_Anchor);
>
>   type Indent_Type (Label : Indent_Labels := Not_Set) is record
>      case Label is
>      when Not_Set =>
>         null;
>
>      when Int =>
>         Int_Offset : Integer;
>
>      ...
>
>      end case;
>   end record;
>
>   package Indent_Vectors is new Ada.Containers.Vectors
>     (Line_Number_Type, Indent_Type);
>
> Then I have code like this:
>
>      for Line in First_Line .. Last_Line loop
>         declare
>            Indent : Indent_Type := Data.Indents (Line);
>         begin
>            case Delta_Indent.Label is
>            when Int =>
>               Indent_Apply_Int (Indent, Delta_Indent.Offset);
>            ...
>            end case;
>
>            Data.Indents.Replace_Element (Line, Indent);
>         end;
>      end loop;
>
> The body of Indent_Apply_Int may change the Label from Not_Set to Int; the 
> other branches of the case statement change Not_Set to the other label 
> values.
>
> I'd like to avoid copying Indent (mostly on general principle; this is not 
> a large object). However, if I use:
>
>   Indent : Indent_Type renames Data.Indents.Reference (Line).Element.all;
>
> and drop the Replace_Element call, then Constraint_Error is raised at the 
> point in Indent_Apply_Int that changes the Label (I'm using GNAT GPL 
> 2017).
>
> I'm not clear if that Constraint_Error is allowed by the ARM. Reference 
> returns a Reference_Type object:
>
>   type Reference_Type (Element : not null access Element_Type) is private
>   with
>      Implicit_Dereference => Element;
>
> Note that Element is of an access type. AARM 4.8 (6) says that allocated 
> objects are constrained by their initial value. AARM 3.10 (26.d/2) says 
> most non-allocated objects accessed via an access-to-object type are not 
> constrained.
>
> So is the type of discriminant Element an access to object type? It 
> doesn't have 'all' in it, so I guess not. Note that the syntax of 
> discriminants does not allow 'all'.

Of course it is an access-to-object type; the only alternative is an 
access-to-subprogram type, and it surely isn't that.

But your question really is, is the object designated by the reference 
object allowed to be constrained (that is, allowed to be an allocated 
object). This doesn't seem to be answered by the RM.

The question IS answered for Update_Element (see A.18.2(142/2)).

I'd argue that the same rule is intended for Reference_Type, but since there 
is no wording requiring it in the RM, it's hard to say that the GNAT 
implementation is wrong. You might try two things:
(1) Try using Update_Element rather than Reference. (A pain, I know.) If 
that does not work either, then GNAT is wrong, file a bug report.
(2) Send a question to Ada-Comment so that the ARG considers the question. I 
don't think we ever intended Update_Element and Reference to work 
differently, but it ought to be discussed.

Note that the answer would be different had you been using 
Indefinite_Vectors. (Those definitely allow the elements to be constrained, 
as those pretty much have to be allocated individually when they are 
created.)

                                         Randy.





> This seems to be a flaw; it would be nice to be able to use Reference in 
> the code above, especially if the copy operation is slow. I guess I could 
> use Update_Element in that case.
>
> In Ada.Containers.Indefinite_Vectors, the Element parameter of 
> Update_Element is allowed to be constrained (AARM A.18.11 (8/2)); that 
> statement is not made in Ada.Containers.Vectors, so the actual Element in 
> a Vector cannot be constrained.
>
> -- Stephe
> 



^ permalink raw reply	[relevance 5%]

* Is Ada.Containers.Vectors.Reference_Type a constrained view?
@ 2017-10-28 11:10 11% Stephen Leake
  2017-11-15  0:38  5% ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Stephen Leake @ 2017-10-28 11:10 UTC (permalink / raw)


I have the following vector type:

   type Indent_Labels is (Not_Set, Int, Anchor, Anchored, Nested_Anchor);

   type Indent_Type (Label : Indent_Labels := Not_Set) is record
      case Label is
      when Not_Set =>
         null;

      when Int => 
         Int_Offset : Integer;

      ...

      end case;
   end record;

   package Indent_Vectors is new Ada.Containers.Vectors 
     (Line_Number_Type, Indent_Type);

Then I have code like this:

      for Line in First_Line .. Last_Line loop
         declare
            Indent : Indent_Type := Data.Indents (Line);
         begin
            case Delta_Indent.Label is
            when Int =>
               Indent_Apply_Int (Indent, Delta_Indent.Offset);
            ...
            end case;

            Data.Indents.Replace_Element (Line, Indent);
         end;
      end loop;

The body of Indent_Apply_Int may change the Label from Not_Set to Int; the other branches of the case statement change Not_Set to the other label values.

I'd like to avoid copying Indent (mostly on general principle; this is not a large object). However, if I use:

   Indent : Indent_Type renames Data.Indents.Reference (Line).Element.all;

and drop the Replace_Element call, then Constraint_Error is raised at the point in Indent_Apply_Int that changes the Label (I'm using GNAT GPL 2017).

I'm not clear if that Constraint_Error is allowed by the ARM. Reference returns a Reference_Type object:

   type Reference_Type (Element : not null access Element_Type) is private
   with
      Implicit_Dereference => Element;

Note that Element is of an access type. AARM 4.8 (6) says that allocated objects are constrained by their initial value. AARM 3.10 (26.d/2) says most non-allocated objects accessed via an access-to-object type are not constrained.

So is the type of discriminant Element an access to object type? It doesn't have 'all' in it, so I guess not. Note that the syntax of discriminants does not allow 'all'.

This seems to be a flaw; it would be nice to be able to use Reference in the code above, especially if the copy operation is slow. I guess I could use Update_Element in that case.

In Ada.Containers.Indefinite_Vectors, the Element parameter of Update_Element is allowed to be constrained (AARM A.18.11 (8/2)); that statement is not made in Ada.Containers.Vectors, so the actual Element in a Vector cannot be constrained.

-- Stephe


^ permalink raw reply	[relevance 11%]

* Re: Ada.Containers.Vectors
  2017-06-26 16:39 13% Ada.Containers.Vectors hnptz
  2017-06-26 18:06  7% ` Ada.Containers.Vectors Per Sandberg
@ 2017-06-27  6:15  7% ` G.B.
  1 sibling, 0 replies; 200+ results
From: G.B. @ 2017-06-27  6:15 UTC (permalink / raw)


On 26.06.17 18:39, hnptz@yahoo.de wrote:
> As a result I get "ambiguous operands for equality" for /= and =. How to resolve these ambiguities?

A bit of a guess, it might be that the message is not
obviously about resolving equality; if I rewrite

exit when f.element(j) /= fmax(j);
...

and

if f.element(j) = fmax(j) then
...

then my compiler responds differently. If implicit_dereference of
holders is going on under the hood, this all might be an effect
of a new feature, and the message could be improved by your
compiler maker.

^ permalink raw reply	[relevance 7%]

* Re: Ada.Containers.Vectors
  2017-06-26 16:39 13% Ada.Containers.Vectors hnptz
@ 2017-06-26 18:06  7% ` Per Sandberg
  2017-06-27  6:15  7% ` Ada.Containers.Vectors G.B.
  1 sibling, 0 replies; 200+ results
From: Per Sandberg @ 2017-06-26 18:06 UTC (permalink / raw)


Hi
A answer is that the compiler don't know if it should use the "=" for
"Constant_Reference_Type'(F (J)))" or "Integer'(F (J))".
Its a bit like:
---------------------------------------
procedure put(Item : Integer);
procedure put(Item : Long_Integer);
procedure put(Item : Long_Long_Integer);
----------------------

And then in the code:
put(2);
-- This wont compile you have to state one of the following:

put(Integer'(2));
put(Long_Integer'(2));
put(Long_Long_Integer'(2));

/Per




Den 2017-06-26 kl. 18:39, skrev hnptz@yahoo.de:
> Here is my code:
> 
> with Ada.Containers; use Ada.Containers;
> with Ada.Containers.Vectors;
> package RGF is
>     package IV is new Vectors(Natural,Integer);
>     use IV;
> procedure GenerateRGF(m : Integer;
>                          f : in out Vector);
> end RGF;
> 
> package body RGF is
>     use IV;
> procedure GenerateRGF(m : Integer;
>                        f : in out Vector) is
>        done : Boolean := False;
>        fmax : Vector;
>        j    : Integer;
>     begin
>        for i in 1..m loop
>           f(i):=1;
>           fmax(i) := 2;
>        end loop;
>        while not done loop
>           j := m+1;
>           loop
>              j := j-1;
>              exit when f(j) /= fmax(j);
>           end loop;
>           if j > 1 then
>              f(j) := f(j)+1;
>              for i in j+1 .. m loop
>                 f(i):=1;
>                 if f(j) = fmax(j) then
>                    fmax(i):=fmax(j)+1;
>                 else
>                    fmax(i):=fmax(j);
>                 end if;
>              end loop;
>           else
>              done := True;
>           end if;
>        end loop;
>     end GenerateRGF;
> 
> end RGF;
> 
> As a result I get "ambiguous operands for equality" for /= and =. How to resolve these ambiguities?
> 
> Best,
> 
> Gilbert
> 
> 
> 

^ permalink raw reply	[relevance 7%]

* Ada.Containers.Vectors
@ 2017-06-26 16:39 13% hnptz
  2017-06-26 18:06  7% ` Ada.Containers.Vectors Per Sandberg
  2017-06-27  6:15  7% ` Ada.Containers.Vectors G.B.
  0 siblings, 2 replies; 200+ results
From: hnptz @ 2017-06-26 16:39 UTC (permalink / raw)


Here is my code:

with Ada.Containers; use Ada.Containers;
with Ada.Containers.Vectors;
package RGF is
   package IV is new Vectors(Natural,Integer);
   use IV;
procedure GenerateRGF(m : Integer;
                        f : in out Vector);
end RGF;

package body RGF is
   use IV;
procedure GenerateRGF(m : Integer;
                      f : in out Vector) is
      done : Boolean := False;
      fmax : Vector;
      j    : Integer;
   begin
      for i in 1..m loop
         f(i):=1;
         fmax(i) := 2;
      end loop;
      while not done loop
         j := m+1;
         loop
            j := j-1;
            exit when f(j) /= fmax(j);
         end loop;
         if j > 1 then
            f(j) := f(j)+1;
            for i in j+1 .. m loop
               f(i):=1;
               if f(j) = fmax(j) then
                  fmax(i):=fmax(j)+1;
               else
                  fmax(i):=fmax(j);
               end if;
            end loop;
         else
            done := True;
         end if;
      end loop;
   end GenerateRGF;

end RGF;

As a result I get "ambiguous operands for equality" for /= and =. How to resolve these ambiguities?

Best,

Gilbert



^ permalink raw reply	[relevance 13%]

* Re: Getting the index for an element in mutually referencing containers
  2017-03-13 23:25  0%                                   ` Simon Wright
@ 2017-03-14  8:25  5%                                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2017-03-14  8:25 UTC (permalink / raw)


On 14/03/2017 00:25, Simon Wright wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> On 2017-03-12 17:44, Simon Wright wrote:
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>
>>>> On 2017-03-12 12:30, Simon Wright wrote:
>>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>>>
>>>>>> On 2017-03-11 22:46, Simon Wright wrote:
>>>>>
>>>>>>> Basically, I (Simon, now) am having trouble thinking of an
>>>>>>> application where reference counting would be an appropriate
>>>>>>> solution.
>>>>>>
>>>>>> As I said, in practice it is all cases when you would have a
>>>>>> container of mutable elements.
>>>>>
>>>>> I had some trouble understanding your point the first time, and
>>>>> skipped over it (sorry).
>>>>>
>>>>> What's the opposite of "mutable"? constant? because, if so, why
>>>>> wouldn't I use Update_Element?
>>>>
>>>> Yes, But it is almost never element update. Usually what you want is
>>>> to call some mutable operations on the element. The language does not
>>>> offer user-defined by-reference or copy-out-copy-in methods to element
>>>> access.
>>>
>>> with Ada.Containers.Vectors;
>>> package Mutable_Elements is
>>>    type Element is record
>>
>> [...]
>>
>> Your example uses access type in Reference_Type which was the point.
>
> There may be pointers under the hood,

Under a straw hat with huge holes meant for ventilation alas exposing 
ugly nasty lack of hair and warts. Pointers are right in the public part 
of Ada.Containers.Vectors.

Even if Reference_Type were an opaque type with no visible access 
discriminant, it would still be a pointer in its semantics with all 
strings attached. Thus if it must be there [*], it must better be a 
smart pointer, e.g. to a reference-counted object.

BTW, reference-counted design gives means to resolve problems with 
at-cursor object deletion and aliased updates in one or another manner.

------------------------
* There should be no helper types needed to access container elements 
"in place".

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


^ permalink raw reply	[relevance 5%]

* Re: Getting the index for an element in mutually referencing containers
  2017-03-12 17:42  0%                                 ` Dmitry A. Kazakov
@ 2017-03-13 23:25  0%                                   ` Simon Wright
  2017-03-14  8:25  5%                                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2017-03-13 23:25 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2017-03-12 17:44, Simon Wright wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>
>>> On 2017-03-12 12:30, Simon Wright wrote:
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>>
>>>>> On 2017-03-11 22:46, Simon Wright wrote:
>>>>
>>>>>> Basically, I (Simon, now) am having trouble thinking of an
>>>>>> application where reference counting would be an appropriate
>>>>>> solution.
>>>>>
>>>>> As I said, in practice it is all cases when you would have a
>>>>> container of mutable elements.
>>>>
>>>> I had some trouble understanding your point the first time, and
>>>> skipped over it (sorry).
>>>>
>>>> What's the opposite of "mutable"? constant? because, if so, why
>>>> wouldn't I use Update_Element?
>>>
>>> Yes, But it is almost never element update. Usually what you want is
>>> to call some mutable operations on the element. The language does not
>>> offer user-defined by-reference or copy-out-copy-in methods to element
>>> access.
>>
>> with Ada.Containers.Vectors;
>> package Mutable_Elements is
>>    type Element is record
>
> [...]
>
> Your example uses access type in Reference_Type which was the point.

There may be pointers under the hood, just like in assembler there are
registers which denote addresses in store, but there are no pointers
explicitly in the code I wrote; so your assertion (that I couldn't call
operations that change a container element) was wrong.

^ permalink raw reply	[relevance 0%]

* Re: Getting the index for an element in mutually referencing containers
  2017-03-12 16:44  7%                               ` Simon Wright
@ 2017-03-12 17:42  0%                                 ` Dmitry A. Kazakov
  2017-03-13 23:25  0%                                   ` Simon Wright
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2017-03-12 17:42 UTC (permalink / raw)


On 2017-03-12 17:44, Simon Wright wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> On 2017-03-12 12:30, Simon Wright wrote:
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>
>>>> On 2017-03-11 22:46, Simon Wright wrote:
>>>
>>>>> Basically, I (Simon, now) am having trouble thinking of an
>>>>> application where reference counting would be an appropriate
>>>>> solution.
>>>>
>>>> As I said, in practice it is all cases when you would have a
>>>> container of mutable elements.
>>>
>>> I had some trouble understanding your point the first time, and
>>> skipped over it (sorry).
>>>
>>> What's the opposite of "mutable"? constant? because, if so, why
>>> wouldn't I use Update_Element?
>>
>> Yes, But it is almost never element update. Usually what you want is
>> to call some mutable operations on the element. The language does not
>> offer user-defined by-reference or copy-out-copy-in methods to element
>> access.
>
> with Ada.Containers.Vectors;
> package Mutable_Elements is
>    type Element is record

[...]

Your example uses access type in Reference_Type which was the point.

Issues to consider are:

1. Two useless Reference_Type type where there should be none, if Ada 
had references.

2. The case of long living multiple references for which Reference_Type 
is no solution.

The case #1 is compiler-managed implicit references or copies. The case 
#2 is user-managed referential helper types. Reference-counted objects 
serve both #1 and #2, being really necessary only for #2.

P.S. It is a pity that Implicit_Dereference type does not have proper 
interface to work with *any* type instead of discriminated records. This 
is design fault when the use case #2 was taken for #1.

P.P.S. Issues with inheritance upon derivation from the container type, 
from the element type, and from both not even mentioned.

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


^ permalink raw reply	[relevance 0%]

* Re: Getting the index for an element in mutually referencing containers
  @ 2017-03-12 16:44  7%                               ` Simon Wright
  2017-03-12 17:42  0%                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2017-03-12 16:44 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2017-03-12 12:30, Simon Wright wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>
>>> On 2017-03-11 22:46, Simon Wright wrote:
>>
>>>> Basically, I (Simon, now) am having trouble thinking of an
>>>> application where reference counting would be an appropriate
>>>> solution.
>>>
>>> As I said, in practice it is all cases when you would have a
>>> container of mutable elements.
>>
>> I had some trouble understanding your point the first time, and
>> skipped over it (sorry).
>>
>> What's the opposite of "mutable"? constant? because, if so, why
>> wouldn't I use Update_Element?
>
> Yes, But it is almost never element update. Usually what you want is
> to call some mutable operations on the element. The language does not
> offer user-defined by-reference or copy-out-copy-in methods to element
> access.

with Ada.Containers.Vectors;
package Mutable_Elements is
   type Element is record
      Numeral : Integer := 0;
   end record;
   procedure Update (E : in out Element);
   package Element_Vectors is new Ada.Containers.Vectors
     (Index_Type => Positive,
      Element_Type => Element);
   Elements : Element_Vectors.Vector;
end Mutable_Elements;

package body Mutable_Elements is
   procedure Update (E : in out Element) is
   begin
      E.Numeral := E.Numeral + 1;
   end Update;
end Mutable_Elements;

with Ada.Text_IO;
with Mutable_Elements;
procedure Mutable_Elements_Test is
   use Mutable_Elements;
begin
   for J in 1 .. 5 loop
      Elements.Append (Element'(Numeral => J));
   end loop;
   
   Elements (4).Numeral := Elements (4).Numeral + 1;
   Ada.Text_IO.Put_Line ("Elements (4).Numeral: "
                           & Elements (4).Numeral'Img);
                           
   Update (Elements (4));
   Ada.Text_IO.Put_Line ("Elements (4).Numeral: "
                           & Elements (4).Numeral'Img);
end Mutable_Elements_Test;

$ ./mutable_elements_test 
Elements (4).Numeral:  5
Elements (4).Numeral:  6


^ permalink raw reply	[relevance 7%]

* Re: Ada 2012 Constraints (WRT an Ada IR)
  @ 2016-12-16 19:59  5%                                                         ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2016-12-16 19:59 UTC (permalink / raw)


<Stefan.Lucks@uni-weimar.de> wrote in message 
news:alpine.DEB.2.20.1612161308590.29766@debian...
...
>If you never call the subprogram with First > Second, it will not raise
>the exception. And if the exception is not raised, anyway, then why, on
>earth, whould you care which exception is not raised?

Only one reason: for compatibility with a previous version of the same 
routine that didn't have the precondition.

The embedded raise expression exists to ease the transition from not having 
preconditions to having them. Without it, one could not take existing code 
like Text_IO or Ada.Containers.Vectors and write it with preconditions. 
Allowing preconditions to be usable only on new code would slow the 
adoption.

Ideally, no one would ever call Ada.Text_IO.Put with a closed file. By 
making that a precondition, we allow tools to detect the mistake so that 
hopefully no one ever is handling Status_Error. But if some existing code is 
handling Status_Error, we can't raise Assertion_Error instead and expect 
that to be OK.

There shouldn't be much need to specify the exception with preconditions for 
new code. Maybe if one needs to be similar to related existing code, but 
that's about it.

                                      Randy.



^ permalink raw reply	[relevance 5%]

* Re: Ada 2005 problem using Iterate
  2016-10-05  7:28  7% Ada 2005 problem using Iterate Roger
@ 2016-10-05  8:15  0% ` Alejandro R. Mosteo
  0 siblings, 0 replies; 200+ results
From: Alejandro R. Mosteo @ 2016-10-05  8:15 UTC (permalink / raw)


On 05/10/16 09:28, Roger wrote:
> I've successfully used Iterate quite often before but the attached code won't work and I can't figure out why.
> Presumably something obvious that I'm blind to!

What I see from checking the a-convec.ads spec

procedure Iterate
      (Container : Vector;
       Process   : not null access procedure (Position : Cursor));

is that your Show_Two_Numbers should expect a Cursor and not and index. 
I don't see any other iterate with a compatible profile.

HTH,
Alex.

> No matter what I try, compiling numbers.adb produces the error messages:
>
> numbers.adb:24:48: expected access to subprogram "Ada.Containers.Vectors." from instance at numbers.ads:17
> numbers.adb:24:48: found type access to procedure "Show_Two_Numbers" defined at line 24
>
> numbers.ads:17 is:
>      package pNumbers_Vector is new  Ada.Containers.Vectors (tNumbers_Index, tNumbers);
> numbers.adb:24 is:
>      Numbers_Vector.Iterate(Show_Two_Numbers'Access);
>
> Can someone tell me what I'm doing wrong?
> Regards,
> Roger
>
> Numbers.ads:
> with Ada.Containers.Vectors;
> package Numbers is
>     type tNumbers_Vector is private;
>     procedure Print_Numbers_Data  (Numbers_Vector : tNumbers_Vector);
> private
>    type tNumbers is record
>       n1                    : Integer := 0;
>       n2                    : Integer := 0;
>    end record;
>
>  subtype tNumbers_Index is Natural;
>  package pNumbers_Vector is new  Ada.Containers.Vectors (tNumbers_Index, tNumbers);
>  type tNumbers_Vector is new pNumbers_Vector.Vector with null record;
> end Numbers;
>
> ============================================================
>
> Numbers.adb:
> with Ada.Text_IO; use Ada.Text_IO;
>
> package body Numbers is
>     Numbers_List : tNumbers_Vector;
>     function  New_Record(n1 : Integer; n2 : Integer) return tnumbers is
>         theRecord : tnumbers := (n1, n2);
>     begin
>         return theRecord;
>     end New_Record;
>
>     --  ----------------------------------------------------------------------------------------------------
>
>     procedure Print_Numbers_Data  (Numbers_Vector : tNumbers_Vector) is
>
>         procedure Show_Two_Numbers(Number_Index : tNumbers_Index) is
>              aNumber_Record    : tnumbers;
>         begin
>              aNumber_Record := Numbers_Vector.Element(Number_Index);
>              Put("Number 1: " & Integer'image(aNumber_Record.n1));
>              Put_Line("      Number 2: " & Integer'image(aNumber_Record.n2));
>          end Show_Two_Numbers;
>
>   begin
>         Numbers_Vector.Iterate(Show_Two_Numbers'Access);
>   end Print_Numbers_Data;
>
>     --  ----------------------------------------------------------------------------------------------------
>
> begin
>     for index in Natural range 0..3 loop
>         Numbers_List.Append(New_Record(index + 2, 2* index + 1));
>     end loop;
> end Numbers;
>

^ permalink raw reply	[relevance 0%]

* Ada 2005 problem using Iterate
@ 2016-10-05  7:28  7% Roger
  2016-10-05  8:15  0% ` Alejandro R. Mosteo
  0 siblings, 1 reply; 200+ results
From: Roger @ 2016-10-05  7:28 UTC (permalink / raw)


I've successfully used Iterate quite often before but the attached code won't work and I can't figure out why.
Presumably something obvious that I'm blind to!
No matter what I try, compiling numbers.adb produces the error messages:

numbers.adb:24:48: expected access to subprogram "Ada.Containers.Vectors." from instance at numbers.ads:17
numbers.adb:24:48: found type access to procedure "Show_Two_Numbers" defined at line 24

numbers.ads:17 is:
     package pNumbers_Vector is new  Ada.Containers.Vectors (tNumbers_Index, tNumbers);
numbers.adb:24 is:
     Numbers_Vector.Iterate(Show_Two_Numbers'Access);

Can someone tell me what I'm doing wrong?
Regards,
Roger

Numbers.ads:
with Ada.Containers.Vectors;
package Numbers is
    type tNumbers_Vector is private;
    procedure Print_Numbers_Data  (Numbers_Vector : tNumbers_Vector);
private
   type tNumbers is record
      n1                    : Integer := 0;
      n2                    : Integer := 0;
   end record;

 subtype tNumbers_Index is Natural;
 package pNumbers_Vector is new  Ada.Containers.Vectors (tNumbers_Index, tNumbers);
 type tNumbers_Vector is new pNumbers_Vector.Vector with null record;
end Numbers;

============================================================

Numbers.adb:
with Ada.Text_IO; use Ada.Text_IO;

package body Numbers is
    Numbers_List : tNumbers_Vector;
    function  New_Record(n1 : Integer; n2 : Integer) return tnumbers is
        theRecord : tnumbers := (n1, n2);
    begin
        return theRecord;
    end New_Record;

    --  ----------------------------------------------------------------------------------------------------

    procedure Print_Numbers_Data  (Numbers_Vector : tNumbers_Vector) is

        procedure Show_Two_Numbers(Number_Index : tNumbers_Index) is
             aNumber_Record    : tnumbers;
        begin
             aNumber_Record := Numbers_Vector.Element(Number_Index);
             Put("Number 1: " & Integer'image(aNumber_Record.n1));
             Put_Line("      Number 2: " & Integer'image(aNumber_Record.n2));
         end Show_Two_Numbers;

  begin
        Numbers_Vector.Iterate(Show_Two_Numbers'Access);
  end Print_Numbers_Data;

    --  ----------------------------------------------------------------------------------------------------

begin
    for index in Natural range 0..3 loop
        Numbers_List.Append(New_Record(index + 2, 2* index + 1));
    end loop;
end Numbers;


^ permalink raw reply	[relevance 7%]

* Re: Limited type in generic package causes double free or corruption
  @ 2016-09-28 18:41  5%   ` onox
  0 siblings, 0 replies; 200+ results
From: onox @ 2016-09-28 18:41 UTC (permalink / raw)


On Wednesday, September 28, 2016 at 6:20:27 PM UTC+2, Jeffrey R. Carter wrote:
> What do you get if you rewrite this function as
> 
> function Get_Tree (Object : Thing) return Trees.Tree is
> begin
>    return Object.My_Tree;
> end Get_Tree;
> 
> ? The two forms should be equivalent.

Then I get (with -gnat2012) this:

>>> (Ada 2005) cannot copy object of a limited type (RM-2005 6.5(5.5/2))
>>> return by reference not permitted in Ada 2005

The error seems to refer to a paragraph in the RM that has been deleted in RM-2012. See http://www.adaic.org/resources/add_content/standards/12aarm/html/AA-6-5.html item 5.6/3 and 5.c/3.

5.6/3 refers to section 7.5 (http://www.adaic.org/resources/add_content/standards/12aarm/html/AA-7-5.html). If I understand 2.9/3 in section 7.5 correctly, my current code should be allowed (which may explain why it does compile in GNAT 2016 according to Anh Vo).

Anyway, Get_Tree is simply meant as a getter. In my non-example code, the tree is constructed in the extended return in Load_Thing.

If Tree is tagged (which it is), doesn't that mean Ada uses copy-by-reference instead of copy-by-value. Or am I mixing things up here?

If it doesn't, then the Tree record is simply copied, and because Ada.Containers.Vectors is controlled, it's basically just a shallow copy?


^ permalink raw reply	[relevance 5%]

* Re: Limited type in generic package causes double free or corruption
  2016-09-28 13:25  5% Limited type in generic package causes double free or corruption onox
  @ 2016-09-28 17:27  0% ` Anh Vo
  1 sibling, 0 replies; 200+ results
From: Anh Vo @ 2016-09-28 17:27 UTC (permalink / raw)


On Wednesday, September 28, 2016 at 6:26:02 AM UTC-7, onox wrote:
> I have a generic package (A) with a limited type (Tree). The generic package is used as a generic formal parameter in another generic package (B). This second generic package has a primitive operation (Get_Tree) that returns a component of a tagged record that is of that limited type. Calling that primitive operation results in a "double free or corruption (fasttop)" message when the program terminates.
> 
> Shouldn't the compiler (GNAT GPL 2015) check that the type in the generic formal parameter (package) is limited and forbid the copying operation? If I remove the "limited" keyword from the type, then the program terminates without any errors.
> 
> Compile via gnatmake c.adb
> 
> I put the example in a separate task, otherwise the program could just hang with 100 % CPU instead of displaying the error and terminating.
> 
> onox
> 
> --  File a.ads
> private with Ada.Containers.Vectors;
> 
> generic
>    Foo : Positive;
> package A is
> 
>    --  Remove "limited" keyword to avoid double-free or corruption
>    type Tree is tagged limited private;
> 
>    function Create_Tree return Tree;
> 
> private
> 
>    package Level_Vectors is new Ada.Containers.Vectors (Positive, Positive);
> 
>    --  Remove "limited" keyword to avoid double-free or corruption
>    type Tree is tagged limited record
>       Levels : Level_Vectors.Vector;
>    end record;
> 
> end A;
> --  End of file a.ads
> 
> --  File a.adb
> package body A is
> 
>    function Create_Tree return Tree is
>    begin
>       return Object : Tree do
>          Object.Levels.Append (10);
>       end return;
>    end Create_Tree;
> 
> end A;
> --  End of file a.adb
> 
> --  File b.ads
> with A;
> 
> generic
>    with package Trees is new A (<>);
> package B is
> 
>    type Thing is tagged limited private;
> 
>    function Load_Thing return Thing;
> 
>    function Get_Tree (Object : Thing) return Trees.Tree;
> 
> private
> 
>    type Thing is tagged limited record
>       My_Tree : Trees.Tree;
>    end record;
> 
> end B;
> --  End of file b.ads
> 
> --  File b.adb
> package body B is
> 
>    function Load_Thing return Thing is
>    begin
>       return Object : Thing := (My_Tree => Trees.Create_Tree) do
>          null;
>       end return;
>    end Load_Thing;
> 
>    --  If Trees.Tree (A.Tree) is limited, shouldn't this function be disallowed?
>    function Get_Tree (Object : Thing) return Trees.Tree is
>      (Object.My_Tree);
> 
> end B;
> --  End of file b.adb
> 
> --  File c.adb
> with Ada.Text_IO;
> with A;
> with B;
> 
> procedure C is
> 
>    task Worker;
> 
>    task body Worker is
>       package AA is new A (1);
>       use AA;
>       package Things is new B (AA);
> 
>       M : Things.Thing := Things.Load_Thing;
>       T : Tree := M.Get_Tree;
>    begin
>       Ada.Text_IO.Put_Line ("Worker thread");
>    end Worker;
> 
> begin
>    Ada.Text_IO.Put_Line ("Environment thread");
> end C;
> --  End of file c.adb

Your codes work fine under GNAT GPL 2016. Of course, you need to pass compiler flag -gnat2012 during compilation.

Anh Vo

^ permalink raw reply	[relevance 0%]

* Limited type in generic package causes double free or corruption
@ 2016-09-28 13:25  5% onox
    2016-09-28 17:27  0% ` Anh Vo
  0 siblings, 2 replies; 200+ results
From: onox @ 2016-09-28 13:25 UTC (permalink / raw)


I have a generic package (A) with a limited type (Tree). The generic package is used as a generic formal parameter in another generic package (B). This second generic package has a primitive operation (Get_Tree) that returns a component of a tagged record that is of that limited type. Calling that primitive operation results in a "double free or corruption (fasttop)" message when the program terminates.

Shouldn't the compiler (GNAT GPL 2015) check that the type in the generic formal parameter (package) is limited and forbid the copying operation? If I remove the "limited" keyword from the type, then the program terminates without any errors.

Compile via gnatmake c.adb

I put the example in a separate task, otherwise the program could just hang with 100 % CPU instead of displaying the error and terminating.

onox

--  File a.ads
private with Ada.Containers.Vectors;

generic
   Foo : Positive;
package A is

   --  Remove "limited" keyword to avoid double-free or corruption
   type Tree is tagged limited private;

   function Create_Tree return Tree;

private

   package Level_Vectors is new Ada.Containers.Vectors (Positive, Positive);

   --  Remove "limited" keyword to avoid double-free or corruption
   type Tree is tagged limited record
      Levels : Level_Vectors.Vector;
   end record;

end A;
--  End of file a.ads

--  File a.adb
package body A is

   function Create_Tree return Tree is
   begin
      return Object : Tree do
         Object.Levels.Append (10);
      end return;
   end Create_Tree;

end A;
--  End of file a.adb

--  File b.ads
with A;

generic
   with package Trees is new A (<>);
package B is

   type Thing is tagged limited private;

   function Load_Thing return Thing;

   function Get_Tree (Object : Thing) return Trees.Tree;

private

   type Thing is tagged limited record
      My_Tree : Trees.Tree;
   end record;

end B;
--  End of file b.ads

--  File b.adb
package body B is

   function Load_Thing return Thing is
   begin
      return Object : Thing := (My_Tree => Trees.Create_Tree) do
         null;
      end return;
   end Load_Thing;

   --  If Trees.Tree (A.Tree) is limited, shouldn't this function be disallowed?
   function Get_Tree (Object : Thing) return Trees.Tree is
     (Object.My_Tree);

end B;
--  End of file b.adb

--  File c.adb
with Ada.Text_IO;
with A;
with B;

procedure C is

   task Worker;

   task body Worker is
      package AA is new A (1);
      use AA;
      package Things is new B (AA);

      M : Things.Thing := Things.Load_Thing;
      T : Tree := M.Get_Tree;
   begin
      Ada.Text_IO.Put_Line ("Worker thread");
   end Worker;

begin
   Ada.Text_IO.Put_Line ("Environment thread");
end C;
--  End of file c.adb


^ permalink raw reply	[relevance 5%]

* Re: Is it possible to make a possibly self-referential type using containers?
  @ 2016-07-31  5:36  5% ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2016-07-31  5:36 UTC (permalink / raw)


On 07/30/2016 05:31 PM, Shark8 wrote:
> Consider something like Forth, IDL, and ASN.1 where there recursion plays a big part in the underlying ideas: the former in its definition of "Word"*, and in the latter two in the defining of types**.
> 
> So, given that the most straightforward way to implement these would be in a self-referencing type it would be nice to be able to use containers for this, perhaps like:

There was a discussion of this on here about a year ago in the context of having
a private type that is self-referential using a container. See

https://groups.google.com/d/msg/comp.lang.ada/SO9olMGfF4o/aGrCFMsVCwAJ

The advantage of using a container is that one doesn't have to deal with the
error-prone aspects of using access types and doing memory management.

I presented a solution there that used a tagged type, an indefinite container of
the 'Class of that type, and a type extension to achieve this:

with Ada.Containers.Indefinite_Vectors;

package P is
   type T (<>) is private;
private
   type Root is tagged null record;

   package Lists is new Ada.Containers.Vectors
      (Index_Type => Positive, Element_Type => Root'Class);

   type T is new Root with record
      List : Lists.Vector;
   end T;
end P;

The intention here is that only values of type T will be stored in such a
vector, so Root and the type extension for T are noise. You also have to
explicitly convert anything retrieved from the list to type T, which is more
noise. But it beats messing with access values.

-- 
Jeff Carter
"I was either in love, or I had smallpox."
Take the Money and Run
137


^ permalink raw reply	[relevance 5%]

* Re: Non_Primitive Operations and Object.Operation Resolution
  2016-04-20 23:59  4% Non_Primitive Operations and Object.Operation Resolution Jeffrey R. Carter
@ 2016-04-21 20:28  0% ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2016-04-21 20:28 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:nf94tt$9iv$1@dont-email.me...
> Some pertinent code from PragmARC.Unbounded_Integers:
>
> package PragmARC.Unbounded_Integers is
>    ...
> private -- PragmARC.Unbounded_Integers
>    type Calculation_Value is mod System.Max_Binary_Modulus;
>
>    Digit_Size : constant := Calculation_Value'Size / 2;
>
>    type Digit_Value is mod 2 ** Digit_Size;
>
>    package Digit_Lists is new Ada.Containers.Vectors (Index_Type => 
> Positive, Element_Type => Digit_Value);
>
>    subtype Digit_List is Digit_Lists.Vector;
>    ...
> end PragmARC.Unbounded_Integers;
>
> package body PragmARC.Unbounded_Integers is
>    ...
>    use type Digit_List;
>
>    function Element (List : Digit_List; Index : Positive) return 
> Digit_Value;
>    -- If Index is a valid index into List, returns the value stored there; 
> otherwise, returns 0
>    ...
>    ... List.Element (Index) ... -- Index is known to be a valid index for 
> List
>    ...
>    ... Element (Left.Digit, I) ... I may not be a valid index for 
> Left.Digit
>
> Until recently, this was no problem. Calls like the 1st example called the 
> primitive Element declared in Digit_Lists. Calls like the 2nd called the 
> non-primitive Element declared in Unbounded_Integers, the only one 
> directly visible.
>
> Recently I've received a couple of reports that this code fails to compile 
> with GNAT GPL 2015. It complains, for calls like List.Element, that it 
> can't resolve Element, pointing to the primitive one in Digit_Lists and 
> the non-primitive one in Unbounded_Integers. I dismissed this as a 
> compiler error, since Object.Operation notation may only be used for 
> primitive operations.

Humm. I would have agreed with you without looking it up, but that's not 
what the wording of 4.1.3 says. It says that "The selector_name shall 
resolve to denote a view of a subprogram declared immediately within the 
declarative region in which an ancestor of the type T is declared." It then 
goes on to make requirements on the first formal parameter of the subprogram 
(to be T, AT'Class, access T, or access AT'Class, where AT is some ancestor 
of T, [recall that "ancestor of T" includes T itself).

Your second function Element certainly qualifies on the secondary rules. I 
would think that it does *not* qualify on the "declarative region" part of 
the rule, but since this isn't your actual code [which is likely to be 
subtly different], I can't say that for sure. If the declarative region of 
some ancestor type of  Digit_Lists includes your second function Element, 
then the call should be ambiguous. (The declarative region includes any 
bodies, so putting the subprogram in the body doesn't change anything.)

If Digit_List has been a derived type, then this Element routine would 
surely qualify (and the call would be ambiguous - although I'm not sure that 
the subprogram would even be legal, as it would be a non-overriding 
homograph of an inherited routine -- that's a rabbit hole I'm not going down 
now as it's not really related to your question).

Assuming that there isn't anything sneaky in the part of the code that you 
didn't provide, it appears to me that GNAT is treating the subtype as one of 
the ancestors which determines the declarative region. I don't think that 
was the intent of the rule, but I can't say for sure. (Is a subtype of T an 
"ancestor of T"? Dunno). The original idea was primitives and class-wides, 
and subtypes don't really fit into that, but the actual wording is what 
matters most.

I just checked the ACATS tests, and I don't see any that would insist on the 
subtype being considered. (But I only checked tests for 4.1.3; sometimes 
some unrelated test touches some corner case.)

If you would like, I could take this to the ARG and see if anyone has any 
insight.

> However, I've more recently been informed that "gcc 6" on FreeBSD gives 
> the same error. While I still think this is a compiler error, I thought 
> I'd ask the language lawyers and ARG members on here to make sure.
>
> Note that Unbounded_Integers is written to ISO/IEC 8652:2007, and so may 
> not compile with an Ada-12 compiler. For GNAT, that means it should be 
> compiled with the -gnat05 option. However, I see no reason why it should 
> not also be valid Ada 12, and it was reported that ggc 6 gives the same 
> error with or without that option.

The wording in question was originally in ISO/IEC 8652:2007; it was changed 
in Ada 2012 but the change is pedantic (having to do with ignoring 
implicitly declared overridden primitives) and doesn't seem to have anything 
to do with this question.

In any case, your code is unnecessarily fragile, as even if GNAT is wrong in 
this particular instance, future program maintenance could make the GNAT 
behavior correct. I'd suggest giving the non-primitive Element a different 
name -- less convinient, perhaps, but if you do that you don't have visit 
grey areas in the RM. :-)

                                               Randy. 



^ permalink raw reply	[relevance 0%]

* Non_Primitive Operations and Object.Operation Resolution
@ 2016-04-20 23:59  4% Jeffrey R. Carter
  2016-04-21 20:28  0% ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Jeffrey R. Carter @ 2016-04-20 23:59 UTC (permalink / raw)


Some pertinent code from PragmARC.Unbounded_Integers:

package PragmARC.Unbounded_Integers is
    ...
private -- PragmARC.Unbounded_Integers
    type Calculation_Value is mod System.Max_Binary_Modulus;

    Digit_Size : constant := Calculation_Value'Size / 2;

    type Digit_Value is mod 2 ** Digit_Size;

    package Digit_Lists is new Ada.Containers.Vectors (Index_Type => Positive, 
Element_Type => Digit_Value);

    subtype Digit_List is Digit_Lists.Vector;
    ...
end PragmARC.Unbounded_Integers;

package body PragmARC.Unbounded_Integers is
    ...
    use type Digit_List;

    function Element (List : Digit_List; Index : Positive) return Digit_Value;
    -- If Index is a valid index into List, returns the value stored there; 
otherwise, returns 0
    ...
    ... List.Element (Index) ... -- Index is known to be a valid index for List
    ...
    ... Element (Left.Digit, I) ... I may not be a valid index for Left.Digit

Until recently, this was no problem. Calls like the 1st example called the 
primitive Element declared in Digit_Lists. Calls like the 2nd called the 
non-primitive Element declared in Unbounded_Integers, the only one directly visible.

Recently I've received a couple of reports that this code fails to compile with 
GNAT GPL 2015. It complains, for calls like List.Element, that it can't resolve 
Element, pointing to the primitive one in Digit_Lists and the non-primitive one 
in Unbounded_Integers. I dismissed this as a compiler error, since 
Object.Operation notation may only be used for primitive operations.

However, I've more recently been informed that "gcc 6" on FreeBSD gives the same 
error. While I still think this is a compiler error, I thought I'd ask the 
language lawyers and ARG members on here to make sure.

Note that Unbounded_Integers is written to ISO/IEC 8652:2007, and so may not 
compile with an Ada-12 compiler. For GNAT, that means it should be compiled with 
the -gnat05 option. However, I see no reason why it should not also be valid Ada 
12, and it was reported that ggc 6 gives the same error with or without that option.

-- 
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

^ permalink raw reply	[relevance 4%]

* Re: Confused about class-wide types
  2016-03-20 13:18  0% ` Shark8
  2016-03-20 13:56  0%   ` Mart van de Wege
@ 2016-03-21 21:54  0%   ` Randy Brukardt
  1 sibling, 0 replies; 200+ results
From: Randy Brukardt @ 2016-03-21 21:54 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:c5f5d5ac-89c4-4b60-9388-f461ed69eb0e@googlegroups.com...
>On Sunday, March 20, 2016 at 5:16:24 AM UTC-6, Mart van de Wege wrote:
>>    package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
>> Element_Type => Event_Ptr);
>
>If you are using Ada 2012, then you can change "Events" to 
>Ada.Containers.Indefinite_Vectors ...

Indefinite_Vectors was actually introduced with the original containers 
library in Ada 2005; you don't need Ada 2012 to use it. (Since there are a 
number of non-GNAT compilers that claim to support Ada 2005, using it 
doesn't lock you in quite as much.)

                                                 Randy.



^ permalink raw reply	[relevance 0%]

* Re: Confused about class-wide types
  2016-03-20 13:18  0% ` Shark8
@ 2016-03-20 13:56  0%   ` Mart van de Wege
  2016-03-21 21:54  0%   ` Randy Brukardt
  1 sibling, 0 replies; 200+ results
From: Mart van de Wege @ 2016-03-20 13:56 UTC (permalink / raw)


Shark8 <onewingedshark@gmail.com> writes:

> On Sunday, March 20, 2016 at 5:16:24 AM UTC-6, Mart van de Wege wrote:
>>    package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
>> 						 Element_Type => Event_Ptr);
>
>
> If you are using Ada 2012, then you can change "Events" to
> Ada.Containers.Indefinite_Vectors with an Element_Type of
> Event'Class... which should, in turn, eliminate the need for any
> pointer-types in the test. (It also has the advantage of not needing
> to check the vector for Null.)

So *that* is what Indefinite_Vectors is for. That would solve my issues,
yes.

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


^ permalink raw reply	[relevance 0%]

* Re: Confused about class-wide types
  2016-03-20 11:15  6% Confused about class-wide types Mart van de Wege
  2016-03-20 12:29  0% ` Dmitry A. Kazakov
  2016-03-20 12:46  0% ` Simon Wright
@ 2016-03-20 13:18  0% ` Shark8
  2016-03-20 13:56  0%   ` Mart van de Wege
  2016-03-21 21:54  0%   ` Randy Brukardt
  2 siblings, 2 replies; 200+ results
From: Shark8 @ 2016-03-20 13:18 UTC (permalink / raw)


On Sunday, March 20, 2016 at 5:16:24 AM UTC-6, Mart van de Wege wrote:
>    package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
> 						 Element_Type => Event_Ptr);


If you are using Ada 2012, then you can change "Events" to Ada.Containers.Indefinite_Vectors with an Element_Type of Event'Class... which should, in turn, eliminate the need for any pointer-types in the test. (It also has the advantage of not needing to check the vector for Null.)


^ permalink raw reply	[relevance 0%]

* Re: Confused about class-wide types
  2016-03-20 11:15  6% Confused about class-wide types Mart van de Wege
  2016-03-20 12:29  0% ` Dmitry A. Kazakov
@ 2016-03-20 12:46  0% ` Simon Wright
  2016-03-20 13:18  0% ` Shark8
  2 siblings, 0 replies; 200+ results
From: Simon Wright @ 2016-03-20 12:46 UTC (permalink / raw)


Mart van de Wege <mvdwege@gmail.com> writes:

> with Ada.Containers.Vectors;
> with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
> package Types_Test is
>    type Event is abstract tagged null record;
>    type Event_Ptr is access Event'Class;
>    type Message_Event is new Event with private;
>    type Message_Event_Ptr is access Message_Event'Class;

You don't need this; Event_Ptr covers Message_Event'Class.

>    procedure Message (M : in out Message_Event_Ptr;
> 		      Mess : in String);

M should be of type Message_Event.

> Test program:
>
> with Types_Test; use Types_Test;
> procedure Test_Type
> is
>    M : Message_Event_Ptr;

This should be of type Event_Ptr.

>    Log : Events.Vector;
> begin
>    M := new Message_Event;
>    Message(M,"Test Message");

Now it gets tricky.

   Message(Message_Event(M.all),"Test Message");

works, because M.All is of type Event'Class and we can do a view
conversion to Message_Event (that's what it was created as in the first
place; we'd get CE if it wasn't).

I think this is difficult because you've introduced operations for the
child (Message_Event) of which the parent (Event) has no analogue at
all. What is the common operation that all Events must support?
Maybe something like

   procedure Handle (E : Event) is abstract;

Your procedure Message is a factory, I think; it might be better as

   function Message (Mess : in String) return Message_Event;

^ permalink raw reply	[relevance 0%]

* Re: Confused about class-wide types
  2016-03-20 11:15  6% Confused about class-wide types Mart van de Wege
@ 2016-03-20 12:29  0% ` Dmitry A. Kazakov
  2016-03-20 12:46  0% ` Simon Wright
  2016-03-20 13:18  0% ` Shark8
  2 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2016-03-20 12:29 UTC (permalink / raw)


On 2016-03-20 12:15, Mart van de Wege wrote:

> I'm finding myself a little confused about the interaction between
> class-wide types.
>
> Here's some example code:
>
> Spec:
>
> with Ada.Containers.Vectors;
> with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
> package Types_Test is
>     type Event is abstract tagged null record;
>     type Event_Ptr is access Event'Class;
>     type Message_Event is new Event with private;
>     type Message_Event_Ptr is access Message_Event'Class;
>     procedure Message (M : in out Message_Event_Ptr;
> 		      Mess : in String);

    function Message (Mess : in String) return Event_Ptr;

>     package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
> 						 Element_Type => Event_Ptr);
> private
>     type Message_Event is new Event with record
>        Message : Unbounded_String;
>     end record;
> end Types_Test;
>
> Test program:
>
> with Types_Test; use Types_Test;
> procedure Test_Type
> is
>     M : Message_Event_Ptr;
>     Log : Events.Vector;
> begin
>     M := new Message_Event;
>     Message(M,"Test Message");
>     Log.Append(M);
> end Test_Type;
 >
> The idea is that Events.Vector should be able to hold different types of
> Events. Yet if I compile it this way, GNAT bombs out with:

    Log.Append (Message ("Test Message"));

> test_type.adb:9:15: expected type "Event_Ptr" defined at types_test.ads:5
> test_type.adb:9:15: found type "Message_Event_Ptr" defined at types_test.ads:7
>
> Obviously, I'm doing something wrong; I'm probably misunderstanding
> something, but what?

Ada has named types equivalence. Event_Ptr and Message_Event_Ptr are two 
independent types regardless what they point to. If you declared

    type Message_Event_Ptr is access Event'Class;

It would not work. Event if you did

    type Message_Event_Ptr is new Event_Ptr;

It still would not.

All this is unrelated to class-wide vs specific types.

BTW, it is a bad idea to use pointers, as bad as using vectors for a 
FIFO or Unbounded_String to keep constant strings. To dynamically 
allocate Unbounded_String which contents is again dynamically allocated 
is quite bizarre. Pointers could be used with queues when messages are 
pre-allocated elsewhere, in order to avoid copying overhead.

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


^ permalink raw reply	[relevance 0%]

* Confused about class-wide types
@ 2016-03-20 11:15  6% Mart van de Wege
  2016-03-20 12:29  0% ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Mart van de Wege @ 2016-03-20 11:15 UTC (permalink / raw)


Hi,

I'm finding myself a little confused about the interaction between
class-wide types.

Here's some example code:

Spec:

with Ada.Containers.Vectors;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
package Types_Test is
   type Event is abstract tagged null record;
   type Event_Ptr is access Event'Class;
   type Message_Event is new Event with private;
   type Message_Event_Ptr is access Message_Event'Class;
   procedure Message (M : in out Message_Event_Ptr;
		      Mess : in String);
   package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
						 Element_Type => Event_Ptr);
private
   type Message_Event is new Event with record
      Message : Unbounded_String;
   end record;
end Types_Test;

Test program:

with Types_Test; use Types_Test;
procedure Test_Type
is
   M : Message_Event_Ptr;
   Log : Events.Vector;
begin
   M := new Message_Event;
   Message(M,"Test Message");
   Log.Append(M);
end Test_Type;

The idea is that Events.Vector should be able to hold different types of
Events. Yet if I compile it this way, GNAT bombs out with:

test_type.adb:9:15: expected type "Event_Ptr" defined at types_test.ads:5
test_type.adb:9:15: found type "Message_Event_Ptr" defined at types_test.ads:7

Obviously, I'm doing something wrong; I'm probably misunderstanding
something, but what?

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.

^ permalink raw reply	[relevance 6%]

* Re: Bounded String question
  @ 2015-11-11 15:41  5%     ` Bob Duff
  0 siblings, 0 replies; 200+ results
From: Bob Duff @ 2015-11-11 15:41 UTC (permalink / raw)


Serge Robyns <serge.robyns@gmail.com> writes:

> Hi Bob,
>
> On Wednesday, 11 November 2015 01:48:43 UTC+1, Bob Duff  wrote:
>> How about:
>> 
>>    function No_Client_Name return T_Client_Name is
>>       (T_Client_Name (P_Strings.Null_Bounded_String));
>
> May idea was to have a "constant" and use language construct/semantic to expose
> that.  I was expecting that the compiler will have more optimization options
> with such a construct than a dynamic construct like above.

I doubt that.  Especially if you put Inline.

>> But why do you need Preelaborate?  It's not all that much use if you use
>> GNAT's static elaboration model.
>
> Just for the sake of "cleanness" and again using language features to express
> my intent as per my "expectations".  Even if I would end up using GNAT in all
> cases.

One possibility is to use the option in GNAT that tells you where to put
pragma Elaborate_All, and put them in by hand.  Then you don't need
Preelaborate.

>> > Maybe I'm using bounded strings completely wrong.
>> 
>> Well, I think the Ada.Strings.Bounded package is way overengineered.
>> So "using Ada.Strings.Bounded" = "using bounded strings wrong".  ;-)
>> I suggest rolling your own.  No need for generics.
>> 
>>    type Bounded_String (Max_Length : Natural := ...) is limited record
>>       Length : Natural := 0;
>>       Chars  : String (1 .. Max_Length);
>>    end record;
>> 
>> along with a few trivial operations.
>
> I tend to agree that the bounded strings seems over-engineered but I'm lacking
> Ada experience to judge that properly.  However it is indeed a pain to use
> compared to other languages where I come from, e.g. C.  I don't know why
> strings are so complex to use in Ada. At various places I've conversions
> between bounded strings and plain strings in order to offer a consistent API to
> my modules. Luckily the package already provide a To_String function.  However,
> I've had to write loads of functions like "To_Client_Name (Name : in String)
> return T_Client_Name is (T_Client_Name (P_Strings.To_Bounded_String (Name));"
> as I haven't found a more direct way to convert a string to the type.

Can't you call the inherited To_Bounded_String directly?

>...This with
> some other oddities in Ada is what do give me a lot of frustrations.  However,
> I do remain decided to proceed with Ada, as I do believe in its core principles
> of allowing developing reliable software.
>
> Now with regards to rolling my own, is this not defeating re-use?  Why shall I
> waste my time on such a feature while I'm having loads of things to do on the
> application itself.

I'm all for reuse.  But in this case, the thing you're reusing causes a
fair amount of trouble, and rolling your own using the type I showed
above is trivial.

> I've been considering using unbounded strings instead but then I'm dropping the
> idea of a bounded storage for my entities.  Most of these "strings" ends up in
> record types which in the end will map to database entities.

Right, if you don't have a known bound, and you're not developing for a
small embedded system, then unbounded strings are often appropriate.
Those are complicated enough that I would not recommend rolling your
own.

Another alternative is Ada.Containers.Vectors instantiated with
Character.

- Bob


^ permalink raw reply	[relevance 5%]

* Re: working with diferent instances of the same generic interface
  @ 2015-09-09 11:08  5%   ` Aitor Alcrudo Sangros
  0 siblings, 0 replies; 200+ results
From: Aitor Alcrudo Sangros @ 2015-09-09 11:08 UTC (permalink / raw)


El miércoles, 9 de septiembre de 2015, 8:38:18 (UTC+2), Jacob Sparre Andersen  escribió:
> Aitor Alcrudo Sangros wrote:
> 
> > Hi, my google-fu can't find how to do this. I think it should be
> > doable but I'm not 100% sure. I'm thankful if anyone helps.
> 
> Your examples don't compile.  Please post a compilable version.
> 
> Also.  It appears to me that you can omit using access types completely.
> 
> Greetings,
> 
> Jacob
> -- 
> There only exist 10 kinds of people: Those who know binary
> numbers and those who don't know binary numbers.

Hi, I'm not really specifically tring to make that code work as is. What I want to know is how can I work with different instances of the same generic interface, doing things like iterating over a collection of them. This is a minimal example of how I am (unsuccessfully ) tring to do so. Anyway this code compiles, then has a runtime exception.

with Ada.Containers.Vectors;
with Ada.Text_IO;   Use Ada.Text_IO;
procedure test is       
   
   package Intro is 
      type Data_type is interface; 

      generic 
         type Readable_Data is abstract new Data_type with private; 
      package Readable is 
         type Readable_Element is interface; 
         type Readable_Element_Access is access all Readable_Element'Class ; 
         function Get_Values (this : Readable_Element ) return Readable_Data'Class 
                           is abstract; 
      end Readable; 

      type state is (OK,KO); 

      generic 
         with package Readable_Reporting is new Readable(<>); 
         use Readable_Reporting ; 
      package Reporting is 
         type Reporting_Element is interface and Readable_Element ; 
         type Reporting_Element_Access is access all Reporting_Element'Class; 
         function Report (This :Reporting_Element  ) return state is Abstract; 
         overriding function Get_Values (this : Reporting_Element ) return 
           Readable_Data'Class is abstract; 
      end Reporting; 
   end Intro; 
  -- use Intro;
   
   
   --ELEMENT A
   type SomeData is new Intro.Data_type with record 
     a :float; 
   end record; 
	
   package Readable_Some is new Intro.Readable( 
      readable_data =>SomeData); 
   package Reporting_Some is new Intro.Reporting(Readable_Some); 
   type Element_type_A is new Readable_Some.Readable_Element 
                                     and Reporting_Some.Reporting_Element 
   with record 
      data :SomeData := SomeData'(a => 0.0 ); 
   end record; 
   type Element_type_A_Access is access all Element_type_A'Class;   
   overriding function Report(This : Element_Type_A ) return Intro.state is ( Intro.KO);
   function Get_Values (this : Element_type_A ) return SomeData'Class is
      (this.data);

   
   -- ELEMENT B   
   type OtherData is new Intro.Data_type with record 
     a :float; 
   end record; 

   package Readable_Other is new Intro.Readable( 
      readable_data =>OtherData); 
   package Reporting_Other is new Intro.Reporting(Readable_Other); 

   type Element_type_B is new Readable_Other.Readable_Element 
                                     and Reporting_Other.Reporting_Element 
   with record 
      data :OtherData; 
   end record;   
   type Element_type_B_Access is access all Element_type_B'Class; 
   function Get_Values (this : Element_type_B ) return OtherData'Class is
      (this.data);
   function Report(This : Element_type_B ) return Intro.state is ( Intro.KO);
   
   --MANAGER --
   package Readable_basic is new Intro.Readable(Intro.Data_type ); 
   package Reporting_basic is new Intro.Reporting(Readable_basic);
   use Reporting_basic;

    package Element_Vector is new
       Ada.Containers.Vectors (Natural,Reporting_basic.Reporting_Element_Access);
     use Element_Vector;
   
   type Manager is tagged record  
     elements :  Element_Vector.Vector;
   end record;
   procedure Add_Element(this : in out Manager ;
                         Element : in Reporting_Element_Access ) is
   begin
      this.elements.Append(Element);
   end Add_Element;
   
   Man : Manager;
   Elm1_ptr : Element_type_A_Access := new Element_type_A;
   Elm2_ptr : Element_type_B_Access := new Element_type_B;
begin  
   Add_Element(Man,Reporting_basic.Reporting_Element_Access(Elm1_ptr));
   Add_Element(Man,Reporting_basic.Reporting_Element_Access(Elm2_ptr));
   put_Line("hello world");
   
end test;

The problem might be in how I am instancing the generic for manager (readable_basic and reporting_basic), but I can't use a box association or unconstrained type in there.

^ permalink raw reply	[relevance 5%]

* working with diferent instances of the same generic interface
@ 2015-09-08 15:10  4% Aitor Alcrudo Sangros
    0 siblings, 1 reply; 200+ results
From: Aitor Alcrudo Sangros @ 2015-09-08 15:10 UTC (permalink / raw)


Hi, my google-fu can't find how to do this. I think it should be doable but I'm not 100% sure. I'm thankful if anyone helps.

I have a generic interface some of my tagged records instance, similar to:

package Intro is
   type Data_type is interface;

   generic
      type Readable_Data is abstract new Data_type with private;
   package Readable is
      type Readable_Element is interface;
      type Readable_Element_Access is access all Readable_Element'Class ;
      function Get_Values (this : Readable_Element ) return Readable_Data'Class
                         is abstract;
   end Readable;

   type state is (OK,KO);

     generic
      with package Readable_Reporting is new Readable(<>);
      use Readable_Reporting ;
   package Reporting is
      type Reporting_Element is interface and Readable_Element ;
      type Reporting_Element_Access is access all Reporting_Element'Class;
      function Report (This :Reporting_Element  ) return state is Abstract;
      overriding function Get_Values (this : Reporting_Element ) return
          Readable_Data'Class is abstract;
   end Reporting;
end Intro;

This has worked with no problem. 
I instance it like this
   SomeData is new Data_type with record
     a :float;
   end record;

   package Readable is new Intro.Readable(
      readable_data =>SomeData);
   package Reporting is new Intro.Reporting(Readable);

   type Element_type_A is new Readable.Readable_Element
     				and Reporting.Reporting_Element 
   						with record
      data :float;
   end record;
   type Element_type_A_Access is access all Element_type_A 'Class;

Now, I have something like this

package Reporter is
   package Readable_basic is new Intro.Readable(Data_type );
   package Reporting_basic is new Intro.Reporting(Readable);
   use Reporting;
   type manager is tagged private;
   procedure Add_Element( This : in out manager ;
                         Element : in Reporting_Element_Access );
private
   package Element_Vector is new
     Ada.Containers.Vectors (Natural,Reporting_Element_Access );
   use Element_Vector ;

   type manager  is tagged record
      Element_List : Element_Vector.Vector;
   end record;
end Reporter ;

this compiles.

Now I try to use it elsewhere

procedure try is
   man :manager ;
   elm1 : Element_type_A_Access ;
   elm2 : Element_type_B_Access ;
begin
   man.add(Reporter.Reporting_basic.Reporting_Element_Access(elm1)  );
   man.add(Reporter.Reporting_basic.Reporting_Element_Access(elm2)  );
end;

This compiles, but produces a runtime exception with invalid interface conversion.

Is there any way to get this to work?.




































^ permalink raw reply	[relevance 4%]

* Re: Indefinite Containers of Indefinite Private Types
  @ 2015-08-07 20:45  6%       ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2015-08-07 20:45 UTC (permalink / raw)


On 08/07/2015 01:13 PM, Bob Duff wrote:
> "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> writes:
> 
>> Yes, of course. The examples are simplified from a more complex case where the
>> container is used in the full type definition. This can be achieved by adding
>> some additional code that is essentially noise, or by using access types.
>> Avoiding access types is worth adding noise, but it would be nice if the noise
>> were unnecessary.
> 
> I'm curious what the "noise" looks like in your case.
> 
> Last time I ran into this problem I think I ended up using a workaround
> that involved access types.  I don't remember the details.

It involves using tagged types, type extension, and a container of a class-wide
type:

with Ada.Containers.Indefinite_Vectors;

package P is
   type T (<>) is private;
private
   type Root is tagged null record;

   package Lists is new Ada.Containers.Vectors
      (Index_Type => Positive, Element_Type => Root'Class);

   type T is new Root with record
      List : Lists.Vector;
   end T;
end P;

The only reason for the type extension is to get the instantiation that can be
used in the full declaration of T. The only objects that will be stored in a
vector are of type T. In addition to the noise of the Root type and the
extension for T, there are type conversions required that are part of the noise.

-- 
Jeff Carter
"From this day on, the official language of San Marcos will be Swedish."
Bananas
28


^ permalink raw reply	[relevance 6%]

* Re: container of a container...
  @ 2015-07-31 21:48  8% ` Niklas Holsti
  0 siblings, 0 replies; 200+ results
From: Niklas Holsti @ 2015-07-31 21:48 UTC (permalink / raw)


On 15-08-01 00:13 , Hedley Rainnie wrote:
> Is it possible to code that? I am coming from the C++ STL world
> where, it  relatively easy to put that together. (a vector of lists
> as an example).
>
> There are many wonderful examples for Ada containers (stacks etc).
> But I have not seen any container[container[...]..] examples.
>
> Being new to Ada, I am sure I have missed something obvious...


Example of a vector of lists of characters:

with Ada.Containers.Vectors;
with Ada.Containers.Doubly_Linked_Lists;

procedure Vec_List
is

    package Char_Lists is new Ada.Containers.Doubly_Linked_Lists (
       Element_Type => Character);

    package Char_List_Vectors is new Ada.Containers.Vectors (
       Index_Type   => Positive,
       Element_Type => Char_Lists.List,
       "="          => Char_Lists."=");

    Vec : Char_List_Vectors.Vector;

    ABC : Char_Lists.List;

begin

    ABC.Append ('A');
    ABC.Append ('B');
    ABC.Append ('C');

    Vec.Replace_Element (3, ABC);

end Vec_List;


-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


^ permalink raw reply	[relevance 8%]

* Re: Running a preprocessor from GPS?
  @ 2015-07-31  7:53  6%                               ` gautier_niouzes
  0 siblings, 0 replies; 200+ results
From: gautier_niouzes @ 2015-07-31  7:53 UTC (permalink / raw)


Le jeudi 30 juillet 2015 22:53:28 UTC+2, EGarrulo a écrit :

> I am not thinking in C++ terms.  I am thinking in terms of patterns
> that I know for managing resources.  So far, I only know the "shared/weak
> pointer" idiom.  If Ada offers something else, besides manual reclamation, I am
> eager to learn about it.

Fantastic, then the example below is for you!
Of course it is a trivial example. You can add a field of type Text to a window type for instance, and the memory will be automatically freed when the window itself is finalized. No pointer, no manual reclamation, no garbage waiting to be collected!... Magic, isn't it ?

--  This test program reads an entire text file into a variable
--  of type Text which is a vector of unbounded strings.

with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO, Ada.Text_IO.Unbounded_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Containers.Vectors;

procedure Text_Container is

  package Text_Pkg is new Ada.Containers.Vectors(Positive, Unbounded_String);
  
  ---------------------
  --  Text container --
  ---------------------
  subtype Text is Text_Pkg.Vector;
  --
  name: constant String:= "text_container.adb";
  t: Text;
  f: File_Type;
begin
  Open(f, In_File, name);
  while not End_of_File(f) loop
    t.Append(Get_Line(f));
  end loop;
  Close(f);
  --
  Create(f, Out_File, "copy_of_" & name);
  for line of t loop
    Put_Line(f, line);
  end loop;
  Close(f);
end;
_________________________
Gautier's Ada programming
http://gautiersblog.blogspot.com/search/label/Ada
NB: follow the above link for a valid e-mail address

^ permalink raw reply	[relevance 6%]

* Re: Deleting elements from a Vector
  2015-04-19 20:27  8% Deleting elements from a Vector Simon Wright
  2015-04-19 21:07  0% ` Jeffrey Carter
@ 2015-04-19 21:12  0% ` Niklas Holsti
  1 sibling, 0 replies; 200+ results
From: Niklas Holsti @ 2015-04-19 21:12 UTC (permalink / raw)


On 15-04-19 23:27 , Simon Wright wrote:
> I need to remove some of the elements from a vector, depending on the
> element. I have the code below, which works for GNAT, but which seems
> distinctly dodgy; in particular, it fails if the last Element is
> negative and therefore gets deleted.

Out of curiosity, how does it fail? Exception?

> The Booch Components have
>
>     procedure Delete_Item_At (It : in out Iterator) is abstract;
>
> (an Iterator is very similar to a Cursor) which is defined to leave the
> Iterator designating the 'next' Element (i.e., the one, is any, you
> would have reached by applying Next to the original Iterator). But I
> don't see any such promise for the Containers.

I could not find such promises. There is a promise that the cursor used 
to delete the element becomes No_Element, as the comment in your code 
(quoted below) says.

It seems that what you are doing is at least unspecified and may be 
erroneous:

- RM A.18.2(251/3) says that any other cursor that designates (or 
designated) the deleted element becomes invalid through the deletion.

- RM A.18.2(2522/2) says that any use of an invalid cursor in "=" or 
Has_Element has unspecified result, and using the cursor with any other 
subprogram from Containers.Vectors is erroneous execution.

So, after the V.Delete (D) in the code below, the cursor C is invalid, 
and on the next loop iteration the condition C /= Vectors.No_Element has 
unspecified result, and the possibly executed Vectors.Element (C) is 
erroneous execution. So don't do that :-)

> Is there a proper idiom for doing this job? Should I maybe go over the
> Vector in reverse order and use the version of Delete that uses the
> index?

Indeed that seems safer. Note also RM A.18.2(240/2..243/2) for the 
definition and properties of an "ambiguous" cursor. This also suggests 
traversing the vector in reverse index order.

> with Ada.Containers.Vectors;
> with Ada.Text_IO; use Ada.Text_IO;
> procedure Deleting_From_Queue is
>     package Vectors is new Ada.Containers.Vectors (Positive, Integer);
>     V : Vectors.Vector;
> begin
>     V.Append (1);
>     V.Append (-1);
>     V.Append (2);
>     V.Append (-2);
>     V.Append (3);
>     declare
>        C : Vectors.Cursor := V.First;
>        D : Vectors.Cursor;
>        use type Vectors.Cursor;
>     begin
>        while C /= Vectors.No_Element loop
>           if Vectors.Element (C) < 0 then
>              Put_Line ("deleting element " & Vectors.Element (C)'Img);
>              D := C;
>              V.Delete (D);  -- D -> No_Element
>           else
>              Put_Line ("skipping element " & Vectors.Element (C)'Img);
>              Vectors.Next (C);
>           end if;
>        end loop;
>     end;
>     Put_Line ("length now " & V.Length'Img);
> end Deleting_From_Queue;
>


-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

^ permalink raw reply	[relevance 0%]

* Re: Deleting elements from a Vector
  2015-04-19 20:27  8% Deleting elements from a Vector Simon Wright
@ 2015-04-19 21:07  0% ` Jeffrey Carter
  2015-04-19 21:12  0% ` Niklas Holsti
  1 sibling, 0 replies; 200+ results
From: Jeffrey Carter @ 2015-04-19 21:07 UTC (permalink / raw)


On 04/19/2015 01:27 PM, Simon Wright wrote:
> I need to remove some of the elements from a vector, depending on the
> element. I have the code below, which works for GNAT, but which seems
> distinctly dodgy; in particular, it fails if the last Element is
> negative and therefore gets deleted.
> 
> Is there a proper idiom for doing this job? Should I maybe go over the
> Vector in reverse order and use the version of Delete that uses the
> index?
> 
> with Ada.Containers.Vectors;
> with Ada.Text_IO; use Ada.Text_IO;
> procedure Deleting_From_Queue is
>    package Vectors is new Ada.Containers.Vectors (Positive, Integer);
>    V : Vectors.Vector;
> begin
>    V.Append (1);
>    V.Append (-1);
>    V.Append (2);
>    V.Append (-2);
>    V.Append (3);
>    declare
>       C : Vectors.Cursor := V.First;
>       D : Vectors.Cursor;
>       use type Vectors.Cursor;
>    begin
>       while C /= Vectors.No_Element loop
>          if Vectors.Element (C) < 0 then
>             Put_Line ("deleting element " & Vectors.Element (C)'Img);
>             D := C;
>             V.Delete (D);  -- D -> No_Element
>          else
>             Put_Line ("skipping element " & Vectors.Element (C)'Img);
>             Vectors.Next (C);
>          end if;
>       end loop;
>    end;
>    Put_Line ("length now " & V.Length'Img);
> end Deleting_From_Queue;

Seems to me that in the general case a cursor becomes invalid after the element
it designates is deleted from the container through another cursor. For most
such containers I'd think doing Next on the cursor before the Delete would work.
However, since a Vector is an unbounded array, the cursor may just be an index,
in which case that wouldn't work. I'd advise always using a Vector as if it were
an array, and iterate over it using indices.

-- 
Jeff Carter
"He didn't get that nose from playing ping-pong."
Never Give a Sucker an Even Break
110

^ permalink raw reply	[relevance 0%]

* Deleting elements from a Vector
@ 2015-04-19 20:27  8% Simon Wright
  2015-04-19 21:07  0% ` Jeffrey Carter
  2015-04-19 21:12  0% ` Niklas Holsti
  0 siblings, 2 replies; 200+ results
From: Simon Wright @ 2015-04-19 20:27 UTC (permalink / raw)


I need to remove some of the elements from a vector, depending on the
element. I have the code below, which works for GNAT, but which seems
distinctly dodgy; in particular, it fails if the last Element is
negative and therefore gets deleted.

The Booch Components have

   procedure Delete_Item_At (It : in out Iterator) is abstract;

(an Iterator is very similar to a Cursor) which is defined to leave the
Iterator designating the 'next' Element (i.e., the one, is any, you
would have reached by applying Next to the original Iterator). But I
don't see any such promise for the Containers.

Is there a proper idiom for doing this job? Should I maybe go over the
Vector in reverse order and use the version of Delete that uses the
index?

with Ada.Containers.Vectors;
with Ada.Text_IO; use Ada.Text_IO;
procedure Deleting_From_Queue is
   package Vectors is new Ada.Containers.Vectors (Positive, Integer);
   V : Vectors.Vector;
begin
   V.Append (1);
   V.Append (-1);
   V.Append (2);
   V.Append (-2);
   V.Append (3);
   declare
      C : Vectors.Cursor := V.First;
      D : Vectors.Cursor;
      use type Vectors.Cursor;
   begin
      while C /= Vectors.No_Element loop
         if Vectors.Element (C) < 0 then
            Put_Line ("deleting element " & Vectors.Element (C)'Img);
            D := C;
            V.Delete (D);  -- D -> No_Element
         else
            Put_Line ("skipping element " & Vectors.Element (C)'Img);
            Vectors.Next (C);
         end if;
      end loop;
   end;
   Put_Line ("length now " & V.Length'Img);
end Deleting_From_Queue;

^ permalink raw reply	[relevance 8%]

* "STORAGE_ERROR : s-intman.adb:139 explicit raise" from record containing a queue from Ada.Containers.Bounded_Synchronized_Queues in Gnat Ada 2014
@ 2015-02-27 19:26  6% jocpaine
  0 siblings, 0 replies; 200+ results
From: jocpaine @ 2015-02-27 19:26 UTC (permalink / raw)


Hi. I've defined a queue type by instantiating Ada.Containers.Bounded_Synchronized_Queues . When I define a record with a field of that type, and then declare a variable of the record type, I get the storage error mentioned in the email subject line. That happens even if I never use the variable. However, if my variable is the queue type, I don't get the error. I'm surprised at that, because I'd expect a one-field record to have exactly the same storage layout as its field, so if one provokes the error, so should the other. That aside though, can anyone suggest a fix? 

Google shows me that similar errors have been reported before (not with the queue types): for example https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42816 , "Bug 42816 - Crash in Ada.Containers.Vectors.Update_Element".

I'm using Gnat Ada 2014: specifically, gnatmake GPL 2014 (20140331) on Ubuntu 14.10 on version 3.16.0-30-generic of the Linux kernel. My program is below. I compiled it by doing
  gnatmake q11
from the file q11.adb . Running it by doing
  ./q11
gives the error.

Here's the program:

with Ada.Containers.Synchronized_Queue_Interfaces;
with Ada.Containers.Bounded_Synchronized_Queues;

procedure Q11 is

 package Job_Queues_Interface is
    new Ada.Containers.Synchronized_Queue_Interfaces
      ( Element_Type => Integer );

  package Job_Queues_Package is
    new Ada.Containers.Bounded_Synchronized_Queues
      ( Queue_Interfaces => Job_Queues_Interface
      , Default_Capacity => 100 
      );

  subtype My_Queue_Type is Job_Queues_Package.Queue; 
      
  type Job_Queue is record
                      Queue: My_Queue_Type;
                    end record;  

  q : Job_Queue;
  -- This is the line causing the error. If I give q
  -- My_Queue_Type instead, the error doesn't happen.
	
begin
  NULL;
end;

Thanks
Jocelyn Ireson-Paine
www.j-paine.org
www.jocelyns-cartoons.uk

^ permalink raw reply	[relevance 6%]

* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics.
  2014-09-23 19:19  5%     ` Robert A Duff
@ 2014-09-23 21:59  0%       ` Jeremiah
  0 siblings, 0 replies; 200+ results
From: Jeremiah @ 2014-09-23 21:59 UTC (permalink / raw)


Thanks everyone for the responses

On Tuesday, September 23, 2014 3:19:52 PM UTC-4, Robert A Duff wrote:
> Jeremiah  writes:
> 
> 
> 
> > Finalize(A)
> 
> > copying B into A
> 
> > Adjust(A)
> 
> 
> 
> Right.
> 
> 
> 
> It might help to look at some examples.  Maybe take a look at the
> 
> GNAT implementation of Ada.Containers.Vectors, in a-convec.ad* .
> 
> 
> 
> - Bob

Thank you, I will.


^ permalink raw reply	[relevance 0%]

* Re: Trying to understand Ada.Finalization.Controlled assignment mechanics.
  @ 2014-09-23 19:19  5%     ` Robert A Duff
  2014-09-23 21:59  0%       ` Jeremiah
  0 siblings, 1 reply; 200+ results
From: Robert A Duff @ 2014-09-23 19:19 UTC (permalink / raw)


Jeremiah <jeremiah.breeden@gmail.com> writes:

> Finalize(A)
> copying B into A
> Adjust(A)

Right.

It might help to look at some examples.  Maybe take a look at the
GNAT implementation of Ada.Containers.Vectors, in a-convec.ad* .

- Bob


^ permalink raw reply	[relevance 5%]

* Re: bug or feature
  @ 2014-09-08  9:43  6% ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2014-09-08  9:43 UTC (permalink / raw)


Charly <carl.weierstrass@googlemail.com> writes:

> I found the following strange behavior of gnat-gpl-2014 (ubuntu linux
> amd64) and I wonder, if it is a bug in gnat:
>
> I habe a package Datum_Pkg that defines a tagged type Datum and
> Datum_Vector (using Ada.Conainers.Vectors). In the main program I want
> to iterate over the vector (all irrelevant lines removed):
[...]

> Line 13 compiles without message but in line 17 I get an error message:
>    subtype indication does not match element type
> But this line should be equivalent to line 13 because of the subtype
> definition in line 6.

Looks like a regression.

I tried this compilable version of your code

with Ada.Containers.Vectors;
with Ada.Text_IO;
procedure Datum is

   package Datum_Pkg is
      type Datum is tagged record
         V : Integer;
      end record;
      function Image (This : Datum) return String is (This.V'Img);
      package Datum_Vectors
        is new Ada.Containers.Vectors (Index_Type   => Positive,
                                       Element_Type => Datum);
      type Datum_Array is array (Positive range 1 .. 10) of Datum;
   end Datum_Pkg;

   subtype Datum is Datum_Pkg.Datum;
   subtype Datum_Vector is Datum_Pkg.Datum_Vectors.Vector;
--   subtype Datum_Vector is Datum_Pkg.Datum_Array;

   D_Vec : Datum_Vector;

begin

   for Dat : Datum_Pkg.Datum of D_Vec loop
      Ada.Text_IO.Put_Line ("Datum=" & Dat.Image);
   end loop;

   for Dat : Datum of D_Vec loop
      Ada.Text_IO.Put_Line ("Datum=" & Dat.Image);
   end loop;

end Datum;

and it fails as you say with GNAT GPL 2014 and FSF GCC 4.9.0. However,
GNAT GPL 2013 and FSF GCC 4.8.1 are both happy.

Not that that would mean it's a regression, necessarily, but if you swap
the definition of subtype Datum_Vector to the array version compilation
succeeds.


^ permalink raw reply	[relevance 6%]

* Re: 'for cursor in container.first loop' bug?
  2014-08-28 17:56  7% 'for cursor in container.first loop' bug? Stephen Leake
@ 2014-08-28 19:56  0% ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2014-08-28 19:56 UTC (permalink / raw)


"Stephen Leake" <stephen_leake@stephe-leake.org> wrote in message 
news:85y4u8xztj.fsf@stephe-leake.org...
> I'm trying to use the 'for cursor in container.first loop' syntax in Ada
> 2012 with my own container, and having lots of problems.
>
> So first I tried a simple example using Ada.Containers.Vector, with GNAT
> 2014:
>
> with Ada.Text_Io; use Ada.Text_Io;
> with Ada.Containers.Vectors;
> procedure Try_Containers
> is
>   package Integer_Vectors is new Ada.Containers.Vectors (Natural, 
> Integer);
>   use Integer_Vectors;
>
>   A : Vector := To_Vector (1, 10);
> begin
>   Loop_1 :
>   for Element of A loop
>      Put_Line ("A (i) => " & Integer'Image (Element));
>      -- can't do Element := 2;
>   end loop Loop_1;
>
>   Loop_2 :
>   for Cursor in First (A) loop
>      Put_Line ("A (I) => " & Integer'Image (Element (Cursor)));
>      Replace_Element (A, Cursor, 2);
>      Reference (A, Cursor) := 2;
>   end loop Loop_2;
>
> end Try_Containers;
>
> This gives compilation errors:
>
> gnatmake -k ../try_containers.adb
> gcc -c -I../ -I- ../try_containers.adb
> try_containers.adb:17:28: invalid prefix in call
> try_containers.adb:17:28: invalid prefix in selected component "I572b"
> gnatmake: "../try_containers.adb" compilation error
>
> Same error (with a different generated name) with GnatPro 7.2.
>
> Commenting out loop_2 gives the expected results.
>
> Am I missing something simple, or is this a compiler bug? At the very
> least, it's not a good error message.

You're missing something simple: "First" is not an iterator (it returns a 
cursor). You need to use one of the functions named "Iterate" that return a 
value that has an iterator type:

Loop_2 :
for Cursor in Iterate (A) loop

I'd still call it a bug, though, because the error message is inpenatrable 
for something simple (a violation of 5.5.2(3/3)). Indeed, this shouldn't 
even resolve.

I checked the two more recent GNAT compilers that I have (Gnatpro 7.2.2 and 
a wavefront), but they both have this message. I'd report it as a bug, 
because you probably wasted at lot of time (and even some of mine) on this 
rather simple mistake.

I was a bit surprised by this, because I thought the new ACATS tests covered 
this. (After some checking...) Interestingly, there is a test that checks 
for this sort of problem, and it produces sensible error messages for cases 
like:
    95.    for Item in Sparse_Cursor loop                            --  
ERROR:
                       |
        >>> cannot iterate over "Cursor"
        >>> to iterate directly over the elements of a container, write "of 
Sparse_Cursor"

   116.    for Item of Sparse_Cursor loop                            --  
ERROR:
               |
        >>> cannot iterate over "Cursor"

But your test (which looks the same to me) produces gibberish. This is 
obviously more subtle than I understand. Time to get some use out of your 
AdaCore support contract. :-)

                                        Randy.




^ permalink raw reply	[relevance 0%]

* 'for cursor in container.first loop' bug?
@ 2014-08-28 17:56  7% Stephen Leake
  2014-08-28 19:56  0% ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Stephen Leake @ 2014-08-28 17:56 UTC (permalink / raw)


I'm trying to use the 'for cursor in container.first loop' syntax in Ada
2012 with my own container, and having lots of problems.

So first I tried a simple example using Ada.Containers.Vector, with GNAT
2014:

with Ada.Text_Io; use Ada.Text_Io;
with Ada.Containers.Vectors;
procedure Try_Containers
is
   package Integer_Vectors is new Ada.Containers.Vectors (Natural, Integer);
   use Integer_Vectors;

   A : Vector := To_Vector (1, 10);
begin
   Loop_1 :
   for Element of A loop
      Put_Line ("A (i) => " & Integer'Image (Element));
      -- can't do Element := 2;
   end loop Loop_1;

   Loop_2 :
   for Cursor in First (A) loop
      Put_Line ("A (I) => " & Integer'Image (Element (Cursor)));
      Replace_Element (A, Cursor, 2);
      Reference (A, Cursor) := 2;
   end loop Loop_2;

end Try_Containers;

This gives compilation errors:

gnatmake -k ../try_containers.adb
gcc -c -I../ -I- ../try_containers.adb
try_containers.adb:17:28: invalid prefix in call
try_containers.adb:17:28: invalid prefix in selected component "I572b"
gnatmake: "../try_containers.adb" compilation error

Same error (with a different generated name) with GnatPro 7.2.

Commenting out loop_2 gives the expected results.

Am I missing something simple, or is this a compiler bug? At the very
least, it's not a good error message.

-- 
-- Stephe

^ permalink raw reply	[relevance 7%]

* Re: Pointer to instance of indefinite array?
  @ 2014-08-13 17:43  6%         ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2014-08-13 17:43 UTC (permalink / raw)


On 08/13/2014 09:06 AM, NiGHTS wrote:
>
> Is it possible to have a constrained array of indefinite arrays without using
> access? In my target program, the "Do_Something_With_Array" function is
> actually an interface to a FIFO queue where groups of indefinite arrays are
> temporarily buffered for use by another task. Of course this will be via an
> entry to a protected object but those details aside how can I construct a
> constrained array of indefinite arrays?

If I need something like that, I'll usually use an array of an unbounded-array 
data structure, which in Ada is found in Ada.Containers.Vectors.

-- 
Jeff Carter
"C++ is vast and dangerous, a sort of Mordor of
programming languages."
Jason R. Fruit
120

^ permalink raw reply	[relevance 6%]

* Re: a new language, designed for safety !
  @ 2014-06-16 23:42  8%                               ` Robert A Duff
  0 siblings, 0 replies; 200+ results
From: Robert A Duff @ 2014-06-16 23:42 UTC (permalink / raw)


Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes:

> On 06/16/2014 02:53 PM, Robert A Duff wrote:
>>
>> It's also unfortunate that Vectors are inherently slow.  

To be clear:  I meant that Ada.Containers.Vectors as defined by the Ada
RM are inherently slow.  Not that all possible vector-like
(i.e. growable-array implementations) are inherently slow.

>>...I wrote a big
>> program recently that made heavy use of Vectors.  The Ada 2012 features
>> were essential for readability -- Vectors would have been unusable
>> otherwise.  But Vectors was way too slow.  So I wrote my own vectors
>> package, using the same 2012 features, and then it was fine -- both
>> readability-wise and efficiency-wise.
>
> If Vectors are inherently slow, how were you able to write one that wasn't?

By writing one that has different semantics -- i.e. does not obey all
the Ada RM rules for Ada.Containers.Vectors.

For example, it has the operations I happened to need (like Append), but
lacks the ones I did not (like Insert).

For example, it supports easy and efficient conversions
Vector <--> array.

For yet another example, it lacks the "tampering" business required by
the RM.  I didn't need all sorts of Cursors pointing into the middle of
Vectors, so I didn't need those run-time checks.

The new Ada 2012 features made my vectors usable from a readability
point of view, just as they have for Ada.Containers.Vectors.

- Bob


^ permalink raw reply	[relevance 8%]

* Lotto simulation 2
@ 2014-06-16  8:03  7% montgrimpulo
  0 siblings, 0 replies; 200+ results
From: montgrimpulo @ 2014-06-16  8:03 UTC (permalink / raw)


Hi,

I want to thank all contributors to my first post on Lotto simulation for their valuable input.
As a conclusion I decided to use the containers.vectors package. Here is my solution. Please
feel free to comment on any aspect.

with Ada.Numerics.Discrete_Random, Ada.Text_IO, Ada.Containers.Vectors;
use Ada.Containers;

procedure Ziehung is
   package IO renames Ada.Text_IO;
   package ball_container is new Vectors (Positive, Positive);
   balls, iball : ball_container.Vector;
   tz, iz       : Integer;
begin
   balls.Set_Length (Length => 49);
   iball.Set_Length (Length => 6);

   for i in 1 .. 49 loop
      balls.Replace_Element (Index => i, New_Item => i);
   end loop;

   tz := 49;
   for i in 1 .. 6 loop
      lottoblock : declare
         subtype z is Positive range 1 .. tz;
         package lb is new Ada.Numerics.Discrete_Random (z);
         glb : lb.Generator;
      begin
         lb.Reset (glb);
         iz := lb.Random (glb);
      end lottoblock;
      iball.Replace_Element
      (Index => i, New_Item => balls.Element (Index => iz));
      balls.Delete (Index => iz, Count => 1);
      tz := tz - 1;
   end loop;

   IO.Put_Line ("Length_b:" & balls.Length'Img);
   IO.Put_Line ("Length_ib:" & iball.Length'Img);

end Ziehung;

Length_b: 43
Length_ib: 6

[2014-06-16] process terminated successfully, elapsed time: 00.21s

^ permalink raw reply	[relevance 7%]

* Re: Safety of unprotected concurrent operations on constant objects
  2014-05-08  8:20  0%                                 ` Dmitry A. Kazakov
@ 2014-05-09 13:14  0%                                   ` Brad Moore
  0 siblings, 0 replies; 200+ results
From: Brad Moore @ 2014-05-09 13:14 UTC (permalink / raw)


On 08/05/2014 2:20 AM, Dmitry A. Kazakov wrote:
> On Wed, 07 May 2014 22:12:13 -0600, Brad Moore wrote:
>
>> On 06/05/2014 2:11 AM, Dmitry A. Kazakov wrote:
>>> On Tue, 06 May 2014 00:00:40 -0600, Brad Moore wrote:
>>>
>>>> On 05/05/2014 10:36 AM, Dmitry A. Kazakov wrote:
>>>>> On Mon, 05 May 2014 09:11:05 -0600, Brad Moore wrote:
>>>>>
>>>>>> Eg. For Ada.Containers.Vectors...
>>>>>>
>>>>>> type Vector is tagged private
>>>>>>        with
>>>>>>           Constant_Indexing => Constant_Reference,
>>>>>>           Variable_Indexing => Reference,
>>>>>>           Default_Iterator  => Iterate,
>>>>>>           Iterator_Element  => Element_Type,
>>>>>>           Task_Safe         => False;
>>>>>>
>>>>>> Then programmers could apply the aspect to their own abstractions, which
>>>>>> better defines the contract of the subprogram or type.
>>>>>
>>>>> Task safety is not a type property. Even for a tagged type an unsafe
>>>>> operation can be defined later on. For non-tagged types it is even less
>>>>> clear which operations must be safe and which not.
>>>>>
>>>>> Furthermore, task-safety cannot be inherited or composed. At least not
>>>>> without massive overhead to prevent deadlocking when two safe types meet as
>>>>> mutable parameters of a safe subprogram.
>>>>
>>>> I agree that such a property is not likely inheritable or composable,
>>>> and I don't think we'd want it to be.  I think conceivably it could
>>>> apply to a type, however. It may be that such an aspect could only be
>>>> applicable to tagged types, and only would apply to the primitive
>>>> subprograms of that type. The aspect, if true would become false for any
>>>> derivations of that type, unless those derived types also explicitly set
>>>> the aspect to True.
>>>
>>> If you limit it to primitive operations then much simpler to do this:
>>>
>>>      type My_Container is tagged ...; -- All operations are unsafe
>>>
>>>      type My_Safe_Container is protected new My_Container with null record;
>>
>> There's quite a difference from what you propose and what I was
>> suggesting. In a nutshell, your idea is to *prescribe* an implementation
>> (by wrapping an existing implementation in mutexes, whereas my wish is
>> to be better able to *describe* an implementation.
>
> To me description that does not prescribe is a lie.

It is true that the Task_Safe aspect would be prescribing some 
restrictions that are meant to enforce the intent as best as possible, 
but it also documents the intent of the programmer. So to be more 
precise, the Task_Safe mechanism doesn't prescribe a specific 
implementation for the programmer. It only prescribes that whatever 
implementation the programmer chooses, it should be task safe.

The "new protected" feature you described, if it were implemented would 
be one possible implementation the programmer could choose, of many.

>
>> Now that Ada has the new contract capabilities in Ada 2012,
>
> You know what I think about these...
>

I take it that you're not a fan of these, but I think there are lots of 
fans out there. In that regard, it's good that contracts aren't mandatory.
If you don't like them, you don't have to use them.


>> it seems
>> like a large hole that there is no way to specify the task safety in the
>> contract as well, so I am wondering about what can be done to improve
>> that situation.
>
>  From the program correctness POV, yes, it is fine to provide some axioms
> for the prover which would use them.

Not just for provers, but also for human readers of the source code. It 
conveys the intent of the programmer to the reader, which might be 
another programmer who wants to use that abstraction.

>
> But this is not the case here. In fact, proving "safety" of an operation is
> easier than proving safety of a combination of "safe" operations.
>
> And you are not going to prove it to hold, as a contract must do. Not even
> to check it at run-time, to annoy the programmer, as Ada 2012 "contracts"
> do.

I think it could be a static check, done at compile time, so it'd be 
similar to a Static_Predicate check, which is another form of contract.
And like a type invariant, which is another form of contract, it doesn't 
"prove" that the invariant can never be false, but it would do
a reasonable amount of checking to catch hopefully most problems, and it
captures the intent of the programmer.

>
>> For example, someone interested in processing a Vector container in
>> parallel would likely not want to use such a feature, because it applies
>> a mutex to every access to the container, when a much more efficient
>> implementation would break the index range into chunks, and
>> a group of worker tasks could process each chunk of the array without
>> any synchronization.
>
> Right, that is a common method, with read-write mutexes used.
>
> Though note, this as well applies to the container library in general. In
> such an application you would not use standard library Vector anyway.
> Because fine-grained locking would not work, while more coarse and
> efficient locking will require interaction with the container inner
> architecture and outer interface.
>
> If you accept language-provided containers without much consideration, you
> can also accept the proposed way to make them kind of safe.
>
>> A worry I'd have is that such a feature might encourage programmers to
>> become lazy and start writing poorer abstractions in lieu of taking the
>> time to write a better one, in respect to functionality, readability,
>> safety, etc.
>
> Yes. As I said, I would prefer delegation support over a specific case of
> compiler-generated wrappers.

Probably an idea that should be explored...

>
>>>> In particular, the aspect could restrict the associated subprogram to
>>>> disallow:
>>>>
>>>> (1) Calls on other non-protected subprograms that are not Pure or
>>>>        Task_Safe;
>>>
>>> But calling a task-safe subprogram from another task-safe subprogram were a
>>> much bigger problem than calling a non-safe subprogram. Protected
>>> operations specifically forbid to do exactly this.
>>
>> That's not correct. Protected procedure's and protected functions are
>> not potentially blocking. A protected procedure of one PO can call
>> another protected procedure of another PO.
>
> I meant 9.5.1 (15). The rationale to have it, IMO, was to ease
> implementations not to care about deadlocks upon locking multiple mutexes.
>
> Same problems will arise when composing task-safe operations. Surely there
> are means to prevent deadlocking whenever the synchronization is done per
> mutexes or per monitors, but these means are not for free.
>
>>> The rules you propose actually are good only for lock-free concurrency.
>>
>> There's million's of simple functions and procedures that do not involve
>> any locking. Integer "+" for example, is completely task safe.
>
> Maybe yes, maybe no. E.g. purely theoretically, consider 64-bit integer "+"
> on i686 in 32-bit mode. The implementation could use movq instruction and
> alike which in turn would have effect on the FPU (turning it off). It will
> restore FPU state upon return, but that would make it unsafe.
>
> In other subthread Randy provided a real-life story for integer "/".
>
>>> Unfortunately only few things can be done lock-free, and most types of
>>> containers certainly not.
>>
>> Containers maybe not in general, but a constant container object without
>> tamper checks could easily be made to be task safe, for functions that
>> query the container, as per the original OP's request.
>
> Yes, but this a very rare scenario (static container), which does not
> deserve special treatment.
>



^ permalink raw reply	[relevance 0%]

* Re: <> syntax in generic formal_package_actual_part
  2014-05-08 23:20  5% ` Adam Beneschan
@ 2014-05-09 13:05  0%   ` G.B.
  0 siblings, 0 replies; 200+ results
From: G.B. @ 2014-05-09 13:05 UTC (permalink / raw)


On 09.05.14 01:20, Adam Beneschan wrote:

>> with Ada.Containers.Vectors;
>> generic
>>      with package G is new Ada.Containers.Vectors (Integer, Positive, <>);
>> package Gen_Pak is end Gen_Pak;
>
> This is illegal, but it doesn't have to be "others => <>"; I believe this is legal:

Thank you!




^ permalink raw reply	[relevance 0%]

* Re: <> syntax in generic formal_package_actual_part
  2014-05-08 22:37  7% <> syntax in generic formal_package_actual_part Georg Bauhaus
@ 2014-05-08 23:20  5% ` Adam Beneschan
  2014-05-09 13:05  0%   ` G.B.
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2014-05-08 23:20 UTC (permalink / raw)


On Thursday, May 8, 2014 3:37:10 PM UTC-7, Georg Bauhaus wrote:
> Hi,
> 
> is a compiler correct in accepting the syntax of these four lines?
> Specifically, if the "<>" the sole text in parentheses, I'd find
> myself at home. But I'm no longer sure with other associations present.
> Should there be an "others =>" before the box?
> 
> 
> with Ada.Containers.Vectors;
> generic
>     with package G is new Ada.Containers.Vectors (Integer, Positive, <>);
> package Gen_Pak is end Gen_Pak;

This is illegal, but it doesn't have to be "others => <>"; I believe this is legal:

 generic
    with package G is new Ada.Containers.Vectors (Integer, Positive, "=" => <>);
 package Gen_Pak is end Gen_Pak;

                                  -- Adam   

^ permalink raw reply	[relevance 5%]

* <> syntax in generic formal_package_actual_part
@ 2014-05-08 22:37  7% Georg Bauhaus
  2014-05-08 23:20  5% ` Adam Beneschan
  0 siblings, 1 reply; 200+ results
From: Georg Bauhaus @ 2014-05-08 22:37 UTC (permalink / raw)


Hi,

is a compiler correct in accepting the syntax of these four lines?
Specifically, if the "<>" the sole text in parentheses, I'd find
myself at home. But I'm no longer sure with other associations present.
Should there be an "others =>" before the box?

with Ada.Containers.Vectors;
generic
    with package G is new Ada.Containers.Vectors (Integer, Positive, <>);
package Gen_Pak is end Gen_Pak;


^ permalink raw reply	[relevance 7%]

* Re: Safety of unprotected concurrent operations on constant objects
  2014-05-08  4:12  0%                               ` Brad Moore
@ 2014-05-08  8:20  0%                                 ` Dmitry A. Kazakov
  2014-05-09 13:14  0%                                   ` Brad Moore
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2014-05-08  8:20 UTC (permalink / raw)


On Wed, 07 May 2014 22:12:13 -0600, Brad Moore wrote:

> On 06/05/2014 2:11 AM, Dmitry A. Kazakov wrote:
>> On Tue, 06 May 2014 00:00:40 -0600, Brad Moore wrote:
>>
>>> On 05/05/2014 10:36 AM, Dmitry A. Kazakov wrote:
>>>> On Mon, 05 May 2014 09:11:05 -0600, Brad Moore wrote:
>>>>
>>>>> Eg. For Ada.Containers.Vectors...
>>>>>
>>>>> type Vector is tagged private
>>>>>       with
>>>>>          Constant_Indexing => Constant_Reference,
>>>>>          Variable_Indexing => Reference,
>>>>>          Default_Iterator  => Iterate,
>>>>>          Iterator_Element  => Element_Type,
>>>>>          Task_Safe         => False;
>>>>>
>>>>> Then programmers could apply the aspect to their own abstractions, which
>>>>> better defines the contract of the subprogram or type.
>>>>
>>>> Task safety is not a type property. Even for a tagged type an unsafe
>>>> operation can be defined later on. For non-tagged types it is even less
>>>> clear which operations must be safe and which not.
>>>>
>>>> Furthermore, task-safety cannot be inherited or composed. At least not
>>>> without massive overhead to prevent deadlocking when two safe types meet as
>>>> mutable parameters of a safe subprogram.
>>>
>>> I agree that such a property is not likely inheritable or composable,
>>> and I don't think we'd want it to be.  I think conceivably it could
>>> apply to a type, however. It may be that such an aspect could only be
>>> applicable to tagged types, and only would apply to the primitive
>>> subprograms of that type. The aspect, if true would become false for any
>>> derivations of that type, unless those derived types also explicitly set
>>> the aspect to True.
>>
>> If you limit it to primitive operations then much simpler to do this:
>>
>>     type My_Container is tagged ...; -- All operations are unsafe
>>
>>     type My_Safe_Container is protected new My_Container with null record;
> 
> There's quite a difference from what you propose and what I was 
> suggesting. In a nutshell, your idea is to *prescribe* an implementation 
> (by wrapping an existing implementation in mutexes, whereas my wish is 
> to be better able to *describe* an implementation.

To me description that does not prescribe is a lie.

> Now that Ada has the new contract capabilities in Ada 2012,

You know what I think about these...

> it seems 
> like a large hole that there is no way to specify the task safety in the 
> contract as well, so I am wondering about what can be done to improve 
> that situation.

From the program correctness POV, yes, it is fine to provide some axioms
for the prover which would use them.

But this is not the case here. In fact, proving "safety" of an operation is
easier than proving safety of a combination of "safe" operations.

And you are not going to prove it to hold, as a contract must do. Not even
to check it at run-time, to annoy the programmer, as Ada 2012 "contracts"
do.

> For example, someone interested in processing a Vector container in 
> parallel would likely not want to use such a feature, because it applies 
> a mutex to every access to the container, when a much more efficient 
> implementation would break the index range into chunks, and
> a group of worker tasks could process each chunk of the array without 
> any synchronization.

Right, that is a common method, with read-write mutexes used.

Though note, this as well applies to the container library in general. In
such an application you would not use standard library Vector anyway.
Because fine-grained locking would not work, while more coarse and
efficient locking will require interaction with the container inner
architecture and outer interface.

If you accept language-provided containers without much consideration, you
can also accept the proposed way to make them kind of safe.

> A worry I'd have is that such a feature might encourage programmers to 
> become lazy and start writing poorer abstractions in lieu of taking the 
> time to write a better one, in respect to functionality, readability, 
> safety, etc.

Yes. As I said, I would prefer delegation support over a specific case of
compiler-generated wrappers.

>>> In particular, the aspect could restrict the associated subprogram to
>>> disallow:
>>>
>>> (1) Calls on other non-protected subprograms that are not Pure or
>>>       Task_Safe;
>>
>> But calling a task-safe subprogram from another task-safe subprogram were a
>> much bigger problem than calling a non-safe subprogram. Protected
>> operations specifically forbid to do exactly this.
> 
> That's not correct. Protected procedure's and protected functions are 
> not potentially blocking. A protected procedure of one PO can call 
> another protected procedure of another PO.

I meant 9.5.1 (15). The rationale to have it, IMO, was to ease
implementations not to care about deadlocks upon locking multiple mutexes. 

Same problems will arise when composing task-safe operations. Surely there
are means to prevent deadlocking whenever the synchronization is done per
mutexes or per monitors, but these means are not for free.

>> The rules you propose actually are good only for lock-free concurrency.
> 
> There's million's of simple functions and procedures that do not involve 
> any locking. Integer "+" for example, is completely task safe.

Maybe yes, maybe no. E.g. purely theoretically, consider 64-bit integer "+"
on i686 in 32-bit mode. The implementation could use movq instruction and
alike which in turn would have effect on the FPU (turning it off). It will
restore FPU state upon return, but that would make it unsafe.

In other subthread Randy provided a real-life story for integer "/".

>> Unfortunately only few things can be done lock-free, and most types of
>> containers certainly not.
> 
> Containers maybe not in general, but a constant container object without 
> tamper checks could easily be made to be task safe, for functions that 
> query the container, as per the original OP's request.

Yes, but this a very rare scenario (static container), which does not
deserve special treatment.

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


^ permalink raw reply	[relevance 0%]

* Re: Safety of unprotected concurrent operations on constant objects
  2014-05-06  8:11  0%                             ` Dmitry A. Kazakov
@ 2014-05-08  4:12  0%                               ` Brad Moore
  2014-05-08  8:20  0%                                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Brad Moore @ 2014-05-08  4:12 UTC (permalink / raw)


On 06/05/2014 2:11 AM, Dmitry A. Kazakov wrote:
> On Tue, 06 May 2014 00:00:40 -0600, Brad Moore wrote:
>
>> On 05/05/2014 10:36 AM, Dmitry A. Kazakov wrote:
>>> On Mon, 05 May 2014 09:11:05 -0600, Brad Moore wrote:
>>>
>>>> Eg. For Ada.Containers.Vectors...
>>>>
>>>> type Vector is tagged private
>>>>       with
>>>>          Constant_Indexing => Constant_Reference,
>>>>          Variable_Indexing => Reference,
>>>>          Default_Iterator  => Iterate,
>>>>          Iterator_Element  => Element_Type,
>>>>          Task_Safe         => False;
>>>>
>>>> Then programmers could apply the aspect to their own abstractions, which
>>>> better defines the contract of the subprogram or type.
>>>
>>> Task safety is not a type property. Even for a tagged type an unsafe
>>> operation can be defined later on. For non-tagged types it is even less
>>> clear which operations must be safe and which not.
>>>
>>> Furthermore, task-safety cannot be inherited or composed. At least not
>>> without massive overhead to prevent deadlocking when two safe types meet as
>>> mutable parameters of a safe subprogram.
>>
>> I agree that such a property is not likely inheritable or composable,
>> and I don't think we'd want it to be.  I think conceivably it could
>> apply to a type, however. It may be that such an aspect could only be
>> applicable to tagged types, and only would apply to the primitive
>> subprograms of that type. The aspect, if true would become false for any
>> derivations of that type, unless those derived types also explicitly set
>> the aspect to True.
>
> If you limit it to primitive operations then much simpler to do this:
>
>     type My_Container is tagged ...; -- All operations are unsafe
>
>     type My_Safe_Container is protected new My_Container with null record;

There's quite a difference from what you propose and what I was 
suggesting. In a nutshell, your idea is to *prescribe* an implementation 
(by wrapping an existing implementation in mutexes, whereas my wish is 
to be better able to *describe* an implementation.
There are lots of ways to provide a task safe implementation, and lots 
of different flavours of task-safe it seems.

Also, the main driver behind what I was suggesting was not to apply the 
aspect to a type, but rather to apply it to a subprogram specification. 
Any subprogram specification, whether its a primitive of a tagged type 
or not.

I only suggested applying the aspect to the primitives of a tagged type, 
as an extension to the idea, as a shorthand for putting the same aspect 
on every primitive subprogram. That part of the idea could be dropped if 
it is too problematic. When the aspect is applied to a type rather than 
a subprogram, I suspect that it would be problematic to apply to 
non-tagged types. If you imagine a function that takes a parameter of a 
task safe type, and another of a non-task safe type type, would the 
function be task safe or not? It seems
clearer that the aspect could work on a tagged type, and only apply to 
the primitives of the tagged type.

As a better example of my main concern, consider the following function.

     type Foo_Range is range 1 .. 1000;

     function Foo (X : Foo_Range) return Integer;

Looking at this, can someone tell me if the function is task-safe or 
not? Who knows? The function might internally use X to update some 
unprotected global statistic variable recording the max, min, and 
average values of all calls for the value of X.

Calling Foo with any combination of arguments concurrently for such a 
case would be dangerous, regardless the values of X.

Now consider that Foo instead uses X as an index to update the value in
some global unprotected array.

In this case, calling Foo from multiple tasks is task-safe, so long as 
two tasks do not call Foo concurrently with the same values of X.

Finally, the function may be task-safe, declaring any state on the stack 
without updating any global variables.

Whether or not such a function can be called concurrently is a pretty 
basic question, but Ada currently doesn't help the reader here.

If you are quite lucky, the programmer might have specified this
in the comments associated with the function. If you are unlucky, the 
programmer didn't later modify the implementation to become task 
un-safe, but neglected to update the comment.

Now that Ada has the new contract capabilities in Ada 2012, it seems 
like a large hole that there is no way to specify the task safety in the 
contract as well, so I am wondering about what can be done to improve 
that situation.

In response to your protected new suggestion. I think there is an idea 
there that could be explored, but I suspect there could be significant 
difficulties in having such an auto-generated protection scheme added to 
Ada. When it comes to task-safety, one size does not fit all.

For example, someone interested in processing a Vector container in 
parallel would likely not want to use such a feature, because it applies 
a mutex to every access to the container, when a much more efficient 
implementation would break the index range into chunks, and
a group of worker tasks could process each chunk of the array without 
any synchronization.

In other cases, moving from a single task design to a multiple task 
design changes the design. A producer/consumer type of usage for a 
bounded container would likely want blocking introduced to calls when 
the container is full, or empty. Simply putting a mutex around all the 
calls is not the best design in that case.

A worry I'd have is that such a feature might encourage programmers to 
become lazy and start writing poorer abstractions in lieu of taking the 
time to write a better one, in respect to functionality, readability, 
safety, etc.

>
> When inherited from, the compiler would override each primitive operation
> and wrap it with a reentrant mutex taken. When an operation gets overridden
> its new body is wrapped. Calling operation within a protected action would
> be bounded error. At least the compiler would be able to maintain mutexes
> of such objects, e.g. order them to prevent deadlocks.
>
> [Better of course, would be to have a decent delegation support]
>
>>> And, just how this contract is supposed to be verified?
>>
>> I see it more as a contract or promise made by the implementer to the
>> users of that subprogram that concurrent calls to the subprogram will
>> work.
>
> You can use this contract no more you can verify it. Because the compiler
> does not know if a call is concurrent or not.
>
>> At this point, I have doubts that the compiler could 100% guarantee that
>> a subprogram call is task safe, but there are likely rules and
>> restrictions that could be applied that would allow the compiler to
>> catch many problems.
>>
>> In particular, the aspect could restrict the associated subprogram to
>> disallow:
>>
>> (1) Calls on other non-protected subprograms that are not Pure or
>>       Task_Safe;
>
> But calling a task-safe subprogram from another task-safe subprogram were a
> much bigger problem than calling a non-safe subprogram. Protected
> operations specifically forbid to do exactly this.

That's not correct. Protected procedure's and protected functions are 
not potentially blocking. A protected procedure of one PO can call 
another protected procedure of another PO.

You could call another
> task-safe operation only on the same object and only if the implementation
> deploys reentrant locking.



>
> The rules you propose actually are good only for lock-free concurrency.

There's million's of simple functions and procedures that do not involve 
any locking. Integer "+" for example, is completely task safe.

> Unfortunately only few things can be done lock-free, and most types of
> containers certainly not.
>

Containers maybe not in general, but a constant container object without 
tamper checks could easily be made to be task safe, for functions that 
query the container, as per the original OP's request.

Regards, Brad

^ permalink raw reply	[relevance 0%]

* Re: Safety of unprotected concurrent operations on constant objects
  2014-05-06  6:00  5%                           ` Brad Moore
@ 2014-05-06  8:11  0%                             ` Dmitry A. Kazakov
  2014-05-08  4:12  0%                               ` Brad Moore
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2014-05-06  8:11 UTC (permalink / raw)


On Tue, 06 May 2014 00:00:40 -0600, Brad Moore wrote:

> On 05/05/2014 10:36 AM, Dmitry A. Kazakov wrote:
>> On Mon, 05 May 2014 09:11:05 -0600, Brad Moore wrote:
>>
>>> Eg. For Ada.Containers.Vectors...
>>>
>>> type Vector is tagged private
>>>      with
>>>         Constant_Indexing => Constant_Reference,
>>>         Variable_Indexing => Reference,
>>>         Default_Iterator  => Iterate,
>>>         Iterator_Element  => Element_Type,
>>>         Task_Safe         => False;
>>>
>>> Then programmers could apply the aspect to their own abstractions, which
>>> better defines the contract of the subprogram or type.
>>
>> Task safety is not a type property. Even for a tagged type an unsafe
>> operation can be defined later on. For non-tagged types it is even less
>> clear which operations must be safe and which not.
>>
>> Furthermore, task-safety cannot be inherited or composed. At least not
>> without massive overhead to prevent deadlocking when two safe types meet as
>> mutable parameters of a safe subprogram.
> 
> I agree that such a property is not likely inheritable or composable, 
> and I don't think we'd want it to be.  I think conceivably it could 
> apply to a type, however. It may be that such an aspect could only be 
> applicable to tagged types, and only would apply to the primitive 
> subprograms of that type. The aspect, if true would become false for any 
> derivations of that type, unless those derived types also explicitly set 
> the aspect to True.

If you limit it to primitive operations then much simpler to do this:

   type My_Container is tagged ...; -- All operations are unsafe

   type My_Safe_Container is protected new My_Container with null record;

When inherited from, the compiler would override each primitive operation
and wrap it with a reentrant mutex taken. When an operation gets overridden
its new body is wrapped. Calling operation within a protected action would
be bounded error. At least the compiler would be able to maintain mutexes
of such objects, e.g. order them to prevent deadlocks.

[Better of course, would be to have a decent delegation support]

>> And, just how this contract is supposed to be verified?
> 
> I see it more as a contract or promise made by the implementer to the 
> users of that subprogram that concurrent calls to the subprogram will 
> work.

You can use this contract no more you can verify it. Because the compiler
does not know if a call is concurrent or not.

> At this point, I have doubts that the compiler could 100% guarantee that 
> a subprogram call is task safe, but there are likely rules and
> restrictions that could be applied that would allow the compiler to 
> catch many problems.
> 
> In particular, the aspect could restrict the associated subprogram to
> disallow:
> 
> (1) Calls on other non-protected subprograms that are not Pure or
>      Task_Safe;

But calling a task-safe subprogram from another task-safe subprogram were a
much bigger problem than calling a non-safe subprogram. Protected
operations specifically forbid to do exactly this. You could call another
task-safe operation only on the same object and only if the implementation
deploys reentrant locking.

The rules you propose actually are good only for lock-free concurrency.
Unfortunately only few things can be done lock-free, and most types of
containers certainly not.

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

^ permalink raw reply	[relevance 0%]

* Re: Safety of unprotected concurrent operations on constant objects
  2014-05-05 16:36  0%                         ` Dmitry A. Kazakov
@ 2014-05-06  6:00  5%                           ` Brad Moore
  2014-05-06  8:11  0%                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Brad Moore @ 2014-05-06  6:00 UTC (permalink / raw)


On 05/05/2014 10:36 AM, Dmitry A. Kazakov wrote:
> On Mon, 05 May 2014 09:11:05 -0600, Brad Moore wrote:
>
>> Eg. For Ada.Containers.Vectors...
>>
>> type Vector is tagged private
>>      with
>>         Constant_Indexing => Constant_Reference,
>>         Variable_Indexing => Reference,
>>         Default_Iterator  => Iterate,
>>         Iterator_Element  => Element_Type,
>>         Task_Safe         => False;
>>
>> Then programmers could apply the aspect to their own abstractions, which
>> better defines the contract of the subprogram or type.
>
> Task safety is not a type property. Even for a tagged type an unsafe
> operation can be defined later on. For non-tagged types it is even less
> clear which operations must be safe and which not.
>
> Furthermore, task-safety cannot be inherited or composed. At least not
> without massive overhead to prevent deadlocking when two safe types meet as
> mutable parameters of a safe subprogram.

I agree that such a property is not likely inheritable or composable, 
and I don't think we'd want it to be.  I think conceivably it could 
apply to a type, however. It may be that such an aspect could only be 
applicable to tagged types, and only would apply to the primitive 
subprograms of that type. The aspect, if true would become false for any 
derivations of that type, unless those derived types also explicitly set 
the aspect to True.

  If such an aspect were explicitly specified as false for the standard 
containers, for instance, it would pretty much describe
the state of affairs today that have been mentioned in this thread,
but hopefully more obvious to the user. That is, you really cant count 
on any of the subprograms in the containers as being task safe, even 
though some of them may be in a given implementation.

However, it might make sense to specify certain primitive subprograms of 
a type as being task safe. For instance, the Element subprogram of the 
Ada.Containers.Vectors is task safe in the current GNAT implementation. 
If that subprogram were to have the aspect specified as True in some 
future version of Ada, then users of that container would at least know 
that particular call is guaranteed to be task safe by its contract. This 
should be fairly straight forward for similar calls that do not modify 
the container or the elements of the container.

It gets trickier for subprograms that do modify the object, such as the 
Replace_Element subprogram of Ada.Containers.Vectors. That call is 
currently task safe in GNAT, so long as two tasks do not attempt to 
replace the same element.The usage of the container object in that call 
itself is task safe, as it does not modify state global to the container 
object, but the elements contained in the container are not task safe. 
So if we wanted to specify concurrent usage for such a subprogram, maybe 
you'd need two aspects; Task_Safe, and Task_Safe_Components.

    procedure Replace_Element
      (Container : in out Vector;
       Index     : Index_Type;
       New_Item  : Element_Type)
      with Task_Safe=>True,
           Task_Safe_Components => False;

>
> And, just how this contract is supposed to be verified?
>

I see it more as a contract or promise made by the implementer to the 
users of that subprogram that concurrent calls to the subprogram will 
work. In other words, the implementer has designed the call to be task 
safe, using whatever means, and has committed to keep the call task safe 
in the future, by having that property associated with the subprogram 
specification.

At this point, I have doubts that the compiler could 100% guarantee that 
a subprogram call is task safe, but there are likely rules and
restrictions that could be applied that would allow the compiler to 
catch many problems.

In particular, the aspect could restrict the associated subprogram to
disallow:

(1) Calls on other non-protected subprograms that are not Pure or
     Task_Safe;

(2) Dependence on global variables that are neither atomic nor task nor
     protected.

These would be static checks that could be applied at compile time.


^ permalink raw reply	[relevance 5%]

* Re: Safety of unprotected concurrent operations on constant objects
  2014-05-05 15:11  4%                       ` Brad Moore
@ 2014-05-05 16:36  0%                         ` Dmitry A. Kazakov
  2014-05-06  6:00  5%                           ` Brad Moore
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2014-05-05 16:36 UTC (permalink / raw)


On Mon, 05 May 2014 09:11:05 -0600, Brad Moore wrote:

> Eg. For Ada.Containers.Vectors...
> 
> type Vector is tagged private
>     with
>        Constant_Indexing => Constant_Reference,
>        Variable_Indexing => Reference,
>        Default_Iterator  => Iterate,
>        Iterator_Element  => Element_Type,
>        Task_Safe         => False;
> 
> Then programmers could apply the aspect to their own abstractions, which 
> better defines the contract of the subprogram or type.

Task safety is not a type property. Even for a tagged type an unsafe
operation can be defined later on. For non-tagged types it is even less
clear which operations must be safe and which not.

Furthermore, task-safety cannot be inherited or composed. At least not
without massive overhead to prevent deadlocking when two safe types meet as
mutable parameters of a safe subprogram.

And, just how this contract is supposed to be verified?

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


^ permalink raw reply	[relevance 0%]

* Re: Safety of unprotected concurrent operations on constant objects
  @ 2014-05-05 15:11  4%                       ` Brad Moore
  2014-05-05 16:36  0%                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Brad Moore @ 2014-05-05 15:11 UTC (permalink / raw)


On 05/05/2014 2:39 AM, Simon Wright wrote:
> Shark8 <OneWingedShark@gmail.com> writes:
>
>> On 05-May-14 15:23, Brad Moore wrote:
>>> In GNAT any read or write operations on a container that set tamper
>>> flags are ironically not task safe
>>
>> That seems very... odd.
>
> Rationale 05 8.1 [1] says (last para)
>
>     "The general rule is given in paragraph 3 of Annex A which says "The
>     implementation shall ensure that each language defined subprogram is
>     reentrant in the sense that concurrent calls on the same subprogram
>     perform as specified, so long as all parameters that could be passed
>     by reference denote nonoverlapping objects." So in other words we
>     have to protect ourselves by using the normal techniques such as
>     protected objects when container operations are invoked concurrently
>     on the same object from multiple tasks even if the operations are
>     only reading from the container.

Except for containers that are already task safe 
(Ada.Containers.Synchronized_Queue_Interfaces)


These paragraph's are actually being revised and are being passed from 
the ARG to WG9 for approval at the June WG9 meeting. If approved, (and 
most likely will be), then the changes apply to the Ada 2012 standard as 
a binding inteterpretation. The changes are mostly clarification to the 
existing intent. The existing wording suggested it only applies to calls 
to the *same* language defined program, whereas the new wording applies 
to calls to *any* language supplied program. Text_IO was also a special 
case when involving standard output. The file parameter is assumed to 
exist, and implicit, so the rule applies to those calls as well.

The new wording is;

  The implementation shall ensure that each language-defined subprogram 
is reentrant in the sense that concurrent calls on any language-defined 
subprogram perform as specified, so long as all parameters that could be 
passed by reference denote nonoverlapping objects.
For the purpose of determining whether concurrent calls on text 
input-output subprograms are required to perform as specified above, 
when calling a subprogram within Text_IO or its children that implicitly 
operates on one of the default input/output files, the subprogram is 
considered to have a parameter of Current_Input or Current_Output (as 
appropriate).

In addition, the following new AARM notes will be added.

" AARM Ramification: So long as the parameters are disjoint, concurrent 
calls on the same language-defined subprogram, and concurrent calls on 
two different language-defined subprograms are required to work. But 
concurrent calls operating on overlapping objects (be they of the same 
or different language-defined subprograms) are NOT required to work 
(being erroneous use of shared variables) unless both subprograms are 
required to pass the associated parameter by-copy.
This rule applies to all language-defined subprograms, including those 
defined in packages that manage some global state (like environment 
variables or the current directory). Unless specified above, such 
subprograms need to work when the explicit parameters are not 
overlapping; in particular, the existence of the global state is not 
considered. Packages with global state may require some locking in order 
to avoid violating this rule."


>
> AARM12 A.18 (5.m) [2] says
>
>     "If containers with similar functionality (but different performance
>     characteristics) are provided (by the implementation or by a
>     secondary standard), we suggest that a prefix be used to identify the
>     class of the functionality: [...] "Ada.Containers.Protected_Maps"
>     (for a map which can be accessed by multiple tasks at one time);
>     [...]"


Another relevant RM paragraph is;

RM 9.10(11-15) which starts;

"Given an action of assigning to an object, and an action of reading or 
updating a part of the same object (or of a neighboring object if the 
two are not independently addressable), then the execution of the 
actions is erroneous unless the actions are sequential."

>
> Personally I'd like to see the implication (that a standard-compliant
> implementation of Containers need not be task-safe unless the Standard
> specifies that it must be) made more visible.
>
> [1] http://www.adaic.org/resources/add_content/standards/05rat/html/Rat-8-1.html
> [2] http://www.ada-auth.org/standards/12aarm/html/AA-A-18.html#p5.m
>

The synchronized keyword in the visible part of the specification of 
Ada.Containers.Synchronous_Queue_Interfaces provides the cue to the 
programmer that the container is task safe.

I'm thinking I'd actually like to see something like a Task_Safe aspect 
that could be applied to type declarations, and subprograms, that would 
make this more clear to users. Having it in the RM is good, but having 
it in the package spec would be even better.

Eg. For Ada.Containers.Vectors...

type Vector is tagged private
    with
       Constant_Indexing => Constant_Reference,
       Variable_Indexing => Reference,
       Default_Iterator  => Iterate,
       Iterator_Element  => Element_Type,
       Task_Safe         => False;

Then programmers could apply the aspect to their own abstractions, which 
better defines the contract of the subprogram or type.


^ permalink raw reply	[relevance 4%]

* Re: Text_IO, was: Re: Something I don't understand
  2014-02-19 21:45  3%                                       ` Niklas Holsti
@ 2014-02-20  9:52  3%                                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2014-02-20  9:52 UTC (permalink / raw)


On Wed, 19 Feb 2014 23:45:47 +0200, Niklas Holsti wrote:

> On 14-02-19 16:13 , Dmitry A. Kazakov wrote:
>> On Wed, 19 Feb 2014 15:20:18 +0200, Niklas Holsti wrote:
>> 
>>> On 14-02-19 11:40 , Dmitry A. Kazakov wrote:
>>>> On Wed, 19 Feb 2014 10:36:29 +0200, Niklas Holsti wrote:
>>>>
>>>>> On 14-02-18 11:31 , Dmitry A. Kazakov wrote:
>>>>>> On Tue, 18 Feb 2014 11:00:44 +0200, Niklas Holsti wrote:
>>>>
>>>>>> To me text buffer, stream, file, string are all instances of the class of
>>>>>> types over which Put dispatches. OK, we can call the abstract root type of
>>>>>> the class "Text."
>>>
>>> My notion of type "Text" is an internal representation of text meant for
>>> human reading and viewing. I don't see any logical need for making this
>>> type a class; there would be only one predefined (and private) type.
>> 
>> Class is needed because there must be more than one implementation of the
>> interface
> 
> Why? It is not expected that there should be more than one
> implementation, in the same Ada program, of Ada.Containers.Vectors, for
> example.

Ada.Containers.Vectors is generic and suffers same issues as Text_IO.

How are you going to handle encoding using single implementation?

> The "Text" type I am talking about is kind of a container for structured
> text ("text" as in meaning (2) below).

What are you going to do when

1. the structure does not match?

2. the content itself varies?

>> and because the interface itself need to be extended in order to
>> have Ada library implementations of reasonable size and complexity.
> 
> That does not convince me. Mere volume (e.g. number of operations) is
> not, to me, a reason for splitting a coherent interface into different
> packages.

It is not the number but ability to add new unknown to language designers
operations.

>>> (2) a text meant only for human reading/viewing and therefore to be
>>> rendered as nicely and readably as the chosen viewing device allows.
>>> That some parts of the text can be seen as sequences of characters is
>>> secondary, and the specific characters and their sequence can change
>>> according to the rendering.
>> 
>> Rendered text is a text so long the reader can reconstruct (1) from (2). So
>> in effect (1) and (2) are equivalent in the sense that both are (1).
> 
> No, text (2) is *not* the result of rendering text (1). Text (2) is
> logically structured text (probably some kind of tree) that has been
> deliberately constructed to have structure.

Whatever. It can have hyperlinks, embedded video and casual games in it.
How are you going to pack this into the RM? How do you find a consensus
what belong to text and what does not? It is just bad design.

> To make it very concrete: under Windows you use Notepad to create text
> (1), but MS-Word to create text (2).

And I dispatch to Notepad, Word, GPS, and other implementations of text
processing and text formats, while it is all text to me.
 
>>> Ada.Text_IO implements mainly (1), with some basic support for
>>> typewriter-style formatting (column spacing, line spacing, page tracking).
>>>
>>> The "Text" type I am talking about aims to be the internal
>>> representation of (2), before rendering on some viewing device.
>> 
>> Why should anybody care about (2)?
> 
> Because users want to see nicely formatted output,

That alone does not justify the architecture of the text formatting library
you propose. It could if you demonstrated that other architectures are
unable to produce nicely formatted output. But they are well capable of. 

But my question was about the internal representations of a certain narrow
subclass of texts you propose to be the universal description of all texts
Ada should support.

>> Why Text_IO should have anything to do with (1)?
> 
> Text (1) can also be processed with Sequential_IO, but usually text (1)
> is divided into syntactical, meaningful tokens, such as keywords or
> decimal numbers, and Text_IO provides (rudimentary) facilities for
> generating such tokens on output, and lexically scanning and evaluating
> such tokens on input.

That is not a property of text. It is of a container of objects of assorted
types.

> The situation is the same in other programming languages, which all
> provide such token-oriented input-output for text (1) files. For example
> printf/scanf in C.

Sequential text processing is not what text is. Nobody argues against
sequential processing, though there are cases where it is not sequential
(e.g. syntax highlighting). But that has little to do with viewing a text
as a sequence of lines or pages or paragraphs etc. Furthermore, there is no
single preferred view of a text medium. Some application might wish to view
it as lines, like compiler do, others might prefer other views. This is why
a class is needed to decouple views from formatting actions and the medium.

>>>> This was attempted before, many many times, actually. From PostScript to
>>>> HTML, an intermediate language that would take care of separating higher
>>>> level formatting from lower level rendering. It never worked how many times
>>>> tried.
>>>
>>> Uh... surely PostScript and HTML "work". I'm pretty sure that a large
>>> fraction, perhaps even a majority of programs today generate most of
>>> their human-readable output as HTML.
>> 
>> Which is why quality of text is so miserable and why the modern OS makes a
>> i486 out of whatever many cores, gigahertz and terabytes monster you run it
>> on.
> 
> You are changing the issue from "works" to "needs a lot of resources and
> is misused". So you lose the argument :-)

But we agreed on the point about resources. So what justifies the orgy?
Ease of use? HTML is very poor on that. Safety? HTML is a joke regarding
it. Maintainability? etc.

>> And of course generating HTML or parsing it is no way simpler than
>> traditional formatting in any sense of that.
> 
> What do you mean by "traditional formatting"?

Without an intermediate layer.

How

   Put (File, "&amp;");

is better than

   Put (File, ''');

?

> I'm not suggesting that the Ada programer would write code to generate
> HTML. The Ada programmer's code would create a "Text" (i.e. a text (2)),
> which can be output as HTML, if it is emitted to a device/file/channel
> which wants HTML.

To put it simple, you don't want HTML. But that was the point I made, HTML
does not work as a middleman. Yet you want to introduce one of your own
hoping it would work better than HTML. It will not.

> I'm not suggesting that Text_IO should be removed. Of course Ada
> programs must be able to read and write files of text (1). It may even
> be desirable to extend the token-level formatting abilities of Text_IO
> or the Image functions, either by more parameters or by templates or
> pictures.

So Text_IO remains a mess, and we add more mess to it.

> But my main point is that if our goal is text formatted to modern
> standards of appearance (with proportional fonts et cetera) then the
> rendering cannot be made token by token, or Put (item) by Put (item);
> the renderer must work on a whole text (2).

It is not "modern", it is simply bad. Bad standards existed in the past and
will appear in the future. It is not Ada's concern, IMO.

>>> If the need is to generate nicely formatted
>>> output, rendered in device-specific ways, and typewriter formatting is
>>> not enough, what is the alternative?
>> 
>> I don't understand the question. It is not about alternatives, the
>> formatting must be done. It is about decomposition of the task into
>> software components. I don't want any middlemen especially such that in
>> order of magnitude more complex than direct formatting.
> 
> Can you give an example of what you mean by "direct formatting"?

Without intermediate objects representing items sufficiently larger than
the things being processed. I want keep formatting "imperative", if you
will.

>> syntax highlighting, WYSIWYG text processing etc.
> 
> If you are talking about interactive applications, at most a screenful
> of text is shown at a time, therefore Text_IO overheads would be
> insignificant.

The design you propose, as you are replacing local operations with ones
dealing with the text as a whole.

> But I think that this kind of application would not use
> Text_IO anyway, because the formatting capabilities of Text_IO would not
> be sufficient.

See? That is because of monolithic design putting imaginary requirements
ahead. This is a wrong way.

>>> I don't see any need for converting a File/Stream *into* Text, unless
>>> the File/Stream is a serialized representation of the full internal
>>> structure of a Text object, in which case the File/Stream structure is
>>> private and normal serialization/deserialization methods apply.
>> 
>> But your proposal was:
>> 
>>    procedure Get (From : in out Text; Value : out Integer);
>>    procedure Get (From : in out File_Type; Item : out Text);
> 
> No, I proposed Put operations, not Get operations. "Text" (that is, text
> (2)) is meant only for output, not for input. For input, use text (1).

Only Text_O? No Text_I at all?

>>> I don't intend that the type "Text" should be so fancy and complete that
>>> it could be used as such to implement an advanced word processor.
>>> Following the same rationale as Ada.Containers, "Text" should provide as
>>> much functionality as can be expected to be useful for (and used by)
>>> many Ada programs and programmers, but programmers requiring high
>>> performance or high/specific functionality would have to implement more
>>> advanced "text" representations themselves.
>> 
>> And so you need it extensible, ergo, a class.
> 
> Not so, if we accept the same rationale as for Ada.Containers: they are
> meant for use in applications without extreme or special demands on the
> performance of the containers.

Ada container library was wrong design from the start. But that is another
story for another day.

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


^ permalink raw reply	[relevance 3%]

* Re: Text_IO, was: Re: Something I don't understand
  @ 2014-02-19 21:45  3%                                       ` Niklas Holsti
  2014-02-20  9:52  3%                                         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Niklas Holsti @ 2014-02-19 21:45 UTC (permalink / raw)


On 14-02-19 16:13 , Dmitry A. Kazakov wrote:
> On Wed, 19 Feb 2014 15:20:18 +0200, Niklas Holsti wrote:
> 
>> On 14-02-19 11:40 , Dmitry A. Kazakov wrote:
>>> On Wed, 19 Feb 2014 10:36:29 +0200, Niklas Holsti wrote:
>>>
>>>> On 14-02-18 11:31 , Dmitry A. Kazakov wrote:
>>>>> On Tue, 18 Feb 2014 11:00:44 +0200, Niklas Holsti wrote:
>>>
>>>>> To me text buffer, stream, file, string are all instances of the class of
>>>>> types over which Put dispatches. OK, we can call the abstract root type of
>>>>> the class "Text."
>>
>> My notion of type "Text" is an internal representation of text meant for
>> human reading and viewing. I don't see any logical need for making this
>> type a class; there would be only one predefined (and private) type.
> 
> Class is needed because there must be more than one implementation of the
> interface

Why? It is not expected that there should be more than one
implementation, in the same Ada program, of Ada.Containers.Vectors, for
example.

The "Text" type I am talking about is kind of a container for structured
text ("text" as in meaning (2) below).

> and because the interface itself need to be extended in order to
> have Ada library implementations of reasonable size and complexity.

That does not convince me. Mere volume (e.g. number of operations) is
not, to me, a reason for splitting a coherent interface into different
packages.

>> By the way, perhaps the word "text" is ambiguous. I think it is time to
>> make a clear distinction between:
>>
>> (1) a text file (sometimes called an "ASCI file"), which is a sequence
>> of basic symbols (e.g. Character or Wide_Character) used to represent
>> *data* for either reading by another program, or for human reading
>> (without formatting), and
> 
> Sequence of symbols is a string.
> 
> Text is at least a sequence of strings (lines).

True for meaning (1), false for meaning (2) (see below).

Text (in meaning (2)) is a sequence of paragraphs (with more structure
at both higher and lower levels). Lines only appear after the text (2)
is rendered.

>> (2) a text meant only for human reading/viewing and therefore to be
>> rendered as nicely and readably as the chosen viewing device allows.
>> That some parts of the text can be seen as sequences of characters is
>> secondary, and the specific characters and their sequence can change
>> according to the rendering.
> 
> Rendered text is a text so long the reader can reconstruct (1) from (2). So
> in effect (1) and (2) are equivalent in the sense that both are (1).

No, text (2) is *not* the result of rendering text (1). Text (2) is
logically structured text (probably some kind of tree) that has been
deliberately constructed to have structure.

There are, of course, forms of text (1), such as HTML or other mark-up
languages, which can represent text (2) and which can be interpreted
into text (2) which can then be rendered. It is also possible to extract
character strings from rendered text (2), discarding the structure --
for example, PDF-to-text conversion.

The existence of such interpretations or lossy conversions does not mean
that text (1) and text (2) are equivalent.

To make it very concrete: under Windows you use Notepad to create text
(1), but MS-Word to create text (2).

>> Ada.Text_IO implements mainly (1), with some basic support for
>> typewriter-style formatting (column spacing, line spacing, page tracking).
>>
>> The "Text" type I am talking about aims to be the internal
>> representation of (2), before rendering on some viewing device.
> 
> Why should anybody care about (2)?

Because users want to see nicely formatted output, and I am suggesting
that text (2) is a way to implement that in Ada, by separating the
logical construction of the text (2) from its rendering. As you say,
this is very like the idea of HTML, but HTML has other aims, too
(hypertext, web forms, ...)

I thought we (that is, you and I, perhaps not the other participants in
the thread) were discussing improving the ability to emit nicely
formatted, readable text from Ada programs. If not, I'll stop here.

> Why Text_IO should have anything to do with (1)?

Text (1) can also be processed with Sequential_IO, but usually text (1)
is divided into syntactical, meaningful tokens, such as keywords or
decimal numbers, and Text_IO provides (rudimentary) facilities for
generating such tokens on output, and lexically scanning and evaluating
such tokens on input.

The situation is the same in other programming languages, which all
provide such token-oriented input-output for text (1) files. For example
printf/scanf in C.

> One of the issues Text_IO had was inference into text issues
> (e.g. pages etc). There is nothing wrong with pages except that 80% of
> formatting and editing does not care about pages.

That is true today, because output to printed paper sheets plays such a
small role today. Decades ago, when such output was very common at least
in information systems, pagination was quite important. Think Report
Generator, page headers/footers, page subtotals, page numbering... Of
course it can all be programmed without pagination support in Text_IO,
but that is the old argument about do-it-yourself vs. standard libraries
or standard language facilities.

OMG, this argument is old... Algol 60 left the definition of I/O
facilities to the implementation... Algol 68 put standard I/O for text
(1) into the language.

> The result is abstraction inversion, and you want to make it
> only worse.

I don't see that at all.

>>>> I'm thinking of two levels of "Put":
>>>>
>>>>    Put (To : in out Text, Item : in String);
>>>>       Add items to a Text, building a logically structured Text,
>>>>       but without rendering it yet. This wil probably need
>>>>       some concept of "points in a Text where more stuff can
>>>>       be inserted" so that the Put can preserve or extend the
>>>>       logical Text structure.
>>>>
>>>>    Put (To : in out File; Item : in Text);
>>>>       Render the Text into some external File.
>>>>
>>>> The Text buffer intermediary means that each level of Put can (if
>>>> desired) be dispatching on one of the parameters, without needing
>>>> multiple dispatch.
>>>
>>> This was attempted before, many many times, actually. From PostScript to
>>> HTML, an intermediate language that would take care of separating higher
>>> level formatting from lower level rendering. It never worked how many times
>>> tried.
>>
>> Uh... surely PostScript and HTML "work". I'm pretty sure that a large
>> fraction, perhaps even a majority of programs today generate most of
>> their human-readable output as HTML.
> 
> Which is why quality of text is so miserable and why the modern OS makes a
> i486 out of whatever many cores, gigahertz and terabytes monster you run it
> on.

You are changing the issue from "works" to "needs a lot of resources and
is misused". So you lose the argument :-)

> And of course generating HTML or parsing it is no way simpler than
> traditional formatting in any sense of that.

What do you mean by "traditional formatting"?

I'm not suggesting that the Ada programer would write code to generate
HTML. The Ada programmer's code would create a "Text" (i.e. a text (2)),
which can be output as HTML, if it is emitted to a device/file/channel
which wants HTML. To other devices the same "Text" could be emitted in
other forms. A GUI toolkit could use its own text-rendering functions to
render the "Text" in a window.

>>> And for sure, it will be even more hated than Text_IO page formatting is,
>>> because the overhead will be far bigger. Imagine describing the semantics
>>> of, say, conversion of File, Stream, String to Text and backward.
>>
>> Overhead compared to what?
> 
> Compared to direct dispatch to the implementation tailored for the give
> medium. Why do I need HTML in order to write a stream or memory string?

Stream or memory string are text (1), not text (2).

I'm not suggesting that Text_IO should be removed. Of course Ada
programs must be able to read and write files of text (1). It may even
be desirable to extend the token-level formatting abilities of Text_IO
or the Image functions, either by more parameters or by templates or
pictures.

But my main point is that if our goal is text formatted to modern
standards of appearance (with proportional fonts et cetera) then the
rendering cannot be made token by token, or Put (item) by Put (item);
the renderer must work on a whole text (2). Just as a browser must have
a whole HTML <table> in order to display any cell of the table in its
final form.

>> If the need is to generate nicely formatted
>> output, rendered in device-specific ways, and typewriter formatting is
>> not enough, what is the alternative?
> 
> I don't understand the question. It is not about alternatives, the
> formatting must be done. It is about decomposition of the task into
> software components. I don't want any middlemen especially such that in
> order of magnitude more complex than direct formatting.

Can you give an example of what you mean by "direct formatting"?

>> The overheads of Text_IO are important only when processing large text
>> *data* files (meaning (1) of "text"). For generating human-readable text
>> (meaning (2)), especially in an interactive context, the overheads are
>> utterly negligible.
> 
> It is not completely true. Huge amounts of readable texts are processed
> without any human intervention. For those Text_IO performance is a big
> problem: Ada project compilation,

Ada source-code is clearly text (1), text as data, even if it is also
human-readable and human-writable. I agree that Text_IO overhead can be
significant in text (1) processing, as I said. I believe that GNAT, for
example, reads its source files by mapping the whole file into memory,
and does not use Text_IO, and not even the OS bulk read() function. (But
such tricks are of course system-specific, non-standard.)

> syntax highlighting, WYSIWYG text processing etc.

If you are talking about interactive applications, at most a screenful
of text is shown at a time, therefore Text_IO overheads would be
insignificant. But I think that this kind of application would not use
Text_IO anyway, because the formatting capabilities of Text_IO would not
be sufficient. My proposed "Text", that is text (2), should work better.

>> I don't see any need for converting a File/Stream *into* Text, unless
>> the File/Stream is a serialized representation of the full internal
>> structure of a Text object, in which case the File/Stream structure is
>> private and normal serialization/deserialization methods apply.
> 
> But your proposal was:
> 
>    procedure Get (From : in out Text; Value : out Integer);
>    procedure Get (From : in out File_Type; Item : out Text);

No, I proposed Put operations, not Get operations. "Text" (that is, text
(2)) is meant only for output, not for input. For input, use text (1).

Not all output is symmetric with input. Think about an audio device: it
is simple to generate audio containing any specified mix and score of
pure tones or instrument voices; it would be much more difficult to
recover the same score and instrument/voice parameters by digitizing and
analysing the generated audio signal. Even more so for the analogous
input/output of video.

>> I don't intend that the type "Text" should be so fancy and complete that
>> it could be used as such to implement an advanced word processor.
>> Following the same rationale as Ada.Containers, "Text" should provide as
>> much functionality as can be expected to be useful for (and used by)
>> many Ada programs and programmers, but programmers requiring high
>> performance or high/specific functionality would have to implement more
>> advanced "text" representations themselves.
> 
> And so you need it extensible, ergo, a class.

Not so, if we accept the same rationale as for Ada.Containers: they are
meant for use in applications without extreme or special demands on the
performance of the containers. The Ada container types are tagged types,
but you cannot create a better-performing or significantly more
functional container by deriving from a container type; you can only
extend the interface with new operations or override some operations to
work differently.

Ok, so that leads to ad-hoc polymorphism, which has some draw-backs, as
you have explained. But IMO not a show-stopper.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .

^ permalink raw reply	[relevance 3%]

* Re: Binary and XML serialization of types
  @ 2014-01-24 17:13  5%         ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2014-01-24 17:13 UTC (permalink / raw)


Georg Bauhaus <rm.dash-bauhaus@futureapps.de> writes:

> On 23.01.14 20:58, hanslad@gmail.com wrote:
>> Thanks Adam,
>>
>> Ok,that makes sense.
>> One more question: Am I on the right path here, or is there a better
>> way to do binary encoding into streams? I want this to perform as
>> fast as possible.
>
> If speed is paramount and the setup permits the same representation
> of data at either end of the line, then using the Read and Write
> procedures for Stream_Element_Array is likely to be unbeatable
> (Streams.Stream_IO).
> This suggests conversion of objects of type Guid into objects of
> type Stream_Element_Array with the help of an 'Address clause or
> through an instance of Unchecked_Conversion. (And some careful
> commenting might be a good idea.)

As long as there's no awkward implementation detail in there .. for
example, GNAT's Ada.Containers.Vectors has

   type Vector is new Controlled with record
      Elements : Elements_Access;
      Last     : Extended_Index := No_Index;
      Busy     : Natural := 0;
      Lock     : Natural := 0;
   end record;

but

   procedure Write
     (Stream    : not null access Root_Stream_Type'Class;
      Container : Vector)
   is
   begin
      Count_Type'Base'Write (Stream, Length (Container));

      for J in Index_Type'First .. Container.Last loop
         Element_Type'Write (Stream, Container.Elements.EA (J));
      end loop;
   end Write;

Also, see the loop at the end of Write; Element_Type might have its own
complicated structure.

I'd say that the fact you're probably going to send the streamed data
over the wire means that speed won't be paramount. On the other hand,
you might want to minimise the number of OS interactions ...


^ permalink raw reply	[relevance 5%]

* Re: Binary and XML serialization of types
  2014-01-23 23:43  0%     ` adambeneschan
@ 2014-01-24  0:58  0%       ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2014-01-24  0:58 UTC (permalink / raw)


<adambeneschan@gmail.com> wrote in message 
news:0301ad03-929d-4c9b-8849-494f7f78c777@googlegroups.com...
> On Thursday, January 23, 2014 2:44:16 PM UTC-8, Simon Wright wrote:
>
>> > What's going on is that if some client package says "with A.Types" and
>> > uses the Guid_Write type, and uses Guid_Write'Write(...) or
>> > Guid_Write'Output(...), the client has to know that there's a Write
>> > routine that isn't the default.  That's why the "for Guid_Write'Write
>> > use ..." has to be in the visible part of A.Types, so that other
>> > clients are allowed to know about it.
>>
>> The type was called Guid.
>
>> But, more importantly, are you sure about this? GNAT's
>> Ada.Containers.Vectors, for example, declares the stream-related stuff
>> in the private part.
>
> Sorry, I think I must have had caffeine deficiency syndrome when I wrote 
> that.
>
> You're right.  Here's what I should have said:
>
> What's going on is that "for Guid'Write" specifies a property, or 
> "aspect", of the type Guid,
> and that needs to be done in the same place where Guid is defined, which 
> in this case is
> the package specification (although it could be in the private part).

To clarify (or confuse?) this more, it does have to be visible if Guid is a 
limited type, because in that case it won't have a usable 'Write unless it 
is explicitly defined. For other types, it can be in the private part.

                                  Randy.





^ permalink raw reply	[relevance 0%]

* Re: Binary and XML serialization of types
  2014-01-23 22:44  5%   ` Simon Wright
@ 2014-01-23 23:43  0%     ` adambeneschan
  2014-01-24  0:58  0%       ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: adambeneschan @ 2014-01-23 23:43 UTC (permalink / raw)


On Thursday, January 23, 2014 2:44:16 PM UTC-8, Simon Wright wrote:

> > What's going on is that if some client package says "with A.Types" and
> > uses the Guid_Write type, and uses Guid_Write'Write(...) or
> > Guid_Write'Output(...), the client has to know that there's a Write
> > routine that isn't the default.  That's why the "for Guid_Write'Write
> > use ..." has to be in the visible part of A.Types, so that other
> > clients are allowed to know about it.
> 
> The type was called Guid.

> But, more importantly, are you sure about this? GNAT's
> Ada.Containers.Vectors, for example, declares the stream-related stuff
> in the private part.

Sorry, I think I must have had caffeine deficiency syndrome when I wrote that.

You're right.  Here's what I should have said:

What's going on is that "for Guid'Write" specifies a property, or "aspect", of the type Guid, and that needs to be done in the same place where Guid is defined, which in this case is the package specification (although it could be in the private part).  

Anyway, my goal was to help the OP understand intuitively why it wouldn't make sense to have a type declared in one package and then allow a property of that type to be changed in some other package.  I hope I got that across, even if I did so badly.

                                 -- Adam 



^ permalink raw reply	[relevance 0%]

* Re: Binary and XML serialization of types
    @ 2014-01-23 22:44  5%   ` Simon Wright
  2014-01-23 23:43  0%     ` adambeneschan
  1 sibling, 1 reply; 200+ results
From: Simon Wright @ 2014-01-23 22:44 UTC (permalink / raw)


adambeneschan@gmail.com writes:

> What's going on is that if some client package says "with A.Types" and
> uses the Guid_Write type, and uses Guid_Write'Write(...) or
> Guid_Write'Output(...), the client has to know that there's a Write
> routine that isn't the default.  That's why the "for Guid_Write'Write
> use ..." has to be in the visible part of A.Types, so that other
> clients are allowed to know about it.

The type was called Guid.

But, more importantly, are you sure about this? GNAT's
Ada.Containers.Vectors, for example, declares the stream-related stuff
in the private part.


^ permalink raw reply	[relevance 5%]

* Re: 'Protected' abstract subprograms
  @ 2014-01-16  0:51  5%                     ` Robert A Duff
  0 siblings, 0 replies; 200+ results
From: Robert A Duff @ 2014-01-16  0:51 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> But Adam's point still holds: with enough ability to qualify the actuals, 
> these rules aren't needed.

Sure.  And my point was that without a complete change in the way
generics work, that would require dozens of additional contractual
specifications.

> I forget the exact case, but I recall something like that fairly recently --  
> we wanted to require some property to match on generic formals, but then 
> many generics would have to be duplicated in order that they would work both 
> with and without that property. (Was it predicates? Can't remember anymore.) 
> To really get proper working, you have to have "with property", "without 
> property", and "don't care about property", but of course the latter brings 
> up the legality issues again.

I'm not sure what property you're referring to, but "limited" is such a
property.  E.g., you'd like to have Ada.Containers.Vectors contain a
Vector type that is limited if and only if the element type is limited.
It works for arrays, but it doesn't work for vectors.  There are other
cases like that -- e.g. you'd like to be able to say that Vector is
derived from Sortable if and only if the Element_Type has relevant
comparison ops.

> In any case, when I was talking about Ada taking privacy seriously, I wasn't 
> thinking about (or caring about) generic instantiation. There is no real 
> privacy for generic specifications, nor can there be (at least with the 
> model of instantiation that Ada uses). [After all, Ada essentially has 
> special rules for the meaning of Legality Rules in generic units - those 
> override all other language principles, whether or not that is a good idea.] 
> Privacy only really matters for concrete things like packages or instances 
> of generic packages.

Right.  That's (part of) why I think the macro expansion model is wrong.
We pretend that the instance is actually there, and complain about
illegalities in its private part, as if those are the fault of the
person who wrote the instantiation (when in fact, that person did NOT
write that private part).

> My point was that that doesn't allow pricavy breaking (for Legality Rules) 
> within normal packages. I can't think of any exceptions to that - there 
> probably is one that I've forgotten but I doubt it invalidates the point.

The only case I know of where the code in a package private part can affect the
legality of code outside that package is this:

    package Recursive_Types is

       type T1 is private;

       package Nested is
          type T2 is private;
       private
          type T2 is record
             X: T1;
          end record;
       end Nested;

    private
       type T1 is record
          Y: Nested.T2; -- Illegal!
       end record;
    end Recursive_Types;

You're not allowed to have two records that are mutually recursive
like that.  So the legality of T1 depends on the code in Nested's
private part.

But one might argue that this case doesn't count, because there's
no separate compilation here.  You can't get this effect if Nested
is changed to a library unit.

- Bob

^ permalink raw reply	[relevance 5%]

* Re: How To Pass Large Object Arguments
  @ 2013-11-25 16:53  6% ` adambeneschan
  0 siblings, 0 replies; 200+ results
From: adambeneschan @ 2013-11-25 16:53 UTC (permalink / raw)


On Saturday, November 23, 2013 11:20:53 PM UTC-8, FritzVonBraun wrote:
> Hello all,
> 
> 
> 
> I am fairly new to Ada and I am wondering how I should pass large 
> parameters to subprograms like arrays or records that contain other 
> components like vectors or lists.
> 
> I did a lot of reading but wasnt able to find a definite answer. the 
> general consensus I got from Barne's book and various blogs and 
> whitepapers from Universities was that in theory IN parameters are 
> copied but the compiler manufacturer is free to implement a reference to 
> the original object and so on. So basically what I found out there is no 
> concrete rule that says "parameter of that size or greater are passed by 
> reference internally"
> 
> So my question is, is there a de facto standard at least? What does Gnat 
> do in such cases? (In all honesty, my programs will never run on 
> anything but Gnat, so other compilers don't really matter to me). I am 
> considering passing objects that I think are too big for a copy 
> operation through an access parameter, but that would basically 
> contradict the principle of problem orientation instead of machine 
> orientation. I would really rather be able to handle these situations 
> without having to worry about the underlying mechanism myself.

The RM has some rules about how certain types are to be passed.  Elementary types are always passed by copy; those are types that essentially aren't broken down into subcomponents, i.e. numbers, enumerations, access types.  This is true even for IN OUT parameters; the value will be passed by copy, and a new value will be copied back after the procedure or function returns.  Tagged types, tasks, protected types, other limited types, and any record or array containing one of those, are always passed by reference.  This is true even for IN parameters.  If the "vectors" or "lists" you're referring to are types in one of the Ada.Containers packages, then they will be passed by reference since Ada.Containers.Vectors.Vector is defined to be a tagged type, and I think that's true for all the other containers.

But for records and arrays that don't fall into one of those categories, it's up to the compiler.  And the compiler's decision may depend on the target processor.  One of our compilers (for a particular RISC-ish target) would pass any record up to four 32-bit words by copy, in registers.  However, for a Pentium, which has very few registers, an implementation like this wouldn't make sense, and there's no point in copying a record to the stack if it isn't required by the language.

So for record and array types that aren't specified by the RM, you shouldn't worry about the parameter passing mechanism, and let the compiler decide what it thinks the best way is.  You should also write code in a way that assumes either one or the other mechanism could be used.  That is, if you call Foo(Param => X) where X's type is some record type, and somewhere while Foo is running, something happens that causes a field in X to be modified, Foo itself may or may not notice that that field has changed if it accesses Param.Field.  (And that's true even if X is passed by reference, since the compiler could generate code that "knows" Param.Field won't change, since it can't tell whether the actual record will change behind its back.)  

                                -- Adam


^ permalink raw reply	[relevance 6%]

* Re: Generics and Child Packages
  @ 2013-08-11 16:51  8%   ` Robert A Duff
  0 siblings, 0 replies; 200+ results
From: Robert A Duff @ 2013-08-11 16:51 UTC (permalink / raw)


sbelmont700@gmail.com writes:

> Though I still don't buy the "children of a generic are a generic"
> explanation.  Semantically there is no difference between a nested
> package and a child package, ...

That ought to be the case, but it's not.  There are lots of
other cases, besides this child-generic thing.  Why is this
legal:

with Ada.Containers.Vectors; use Ada;
package P is
   type T is private;
private
   type T is (Red);
end P;

package P.Q is
   package T_Vectors is new Containers.Vectors
     (Index_Type => Positive, Element_Type => T);
end P.Q;

but this is illegal:

with Ada.Containers.Vectors; use Ada;
package P is
   type T is private;

   package Q is
      package T_Vectors is new Containers.Vectors
        (Index_Type => Positive, Element_Type => T);
   end Q;
private
   type T is (Red);
end P;

For that matter, why should the following be illegal:

package P is
   with Something;
   package Q is
   end Q;
end P;

- Bob

^ permalink raw reply	[relevance 8%]

* Re: How can I declare a collection of an interface?
  2013-08-02 16:39  5% How can I declare a collection of an interface? Graham Stark
  2013-08-02 16:53  0% ` Eryndlia Mavourneen
@ 2013-08-02 18:28  6% ` Adam Beneschan
  1 sibling, 0 replies; 200+ results
From: Adam Beneschan @ 2013-08-02 18:28 UTC (permalink / raw)


On Friday, August 2, 2013 9:39:14 AM UTC-7, Graham Stark wrote:
> Hi,
> 
>    if I have (say):
> 
> type Person is interface;
> 
> and I want to declare a collection of Person, how can I declare the type I'd need? I've tried:
> 
> type PA is array(1..2) of Person;

Assuming you want the array elements to be possibly different types that are derived from Person, you'll need to declare an access type:

  type Person_Acc is access all Person'Class;
  type PA is array(1..2) of Person_Acc;

Since an object of type Person'Class could be lots of other types, possibly of different sizes, Ada can't create an array of Person'Class.  Arrays are only useful when all the elements are the same type.  That's why you have to use an access type.  If you're coming from another language such as Java or C#, those languages will automatically give you a pointer if you declare an array of some class type.  Ada doesn't.  You have to tell it you want an access type (i.e. pointer).  'Class means "an object of this type or some type derived from it"; this is something else that Java/C# give you automatically, but in Ada you have to be explicit about this because sometimes you don't want that automatically.

> or
> 
> package PV is new Ada.Containers.Vectors( Positive, Person );
>  
> and the same with 'Class.

You could use Person_Acc in the same way:

  package PV is new Ada.Containers.Vectors (Positive, Person_Acc);

However, the Ada.Containers packages are able to handle "indefinite types" themselves, and they should take care of the pointer stuff for you.  To do this, you have to use Indefinite_Vectors instead of Vectors:

  package PV is new Ada.Containers.Indefinite_Vectors (Positive, Person'Class);

Person'Class is an "indefinite" type because we don't know beforehand what the actual type of the object will be.

                              -- Adam

^ permalink raw reply	[relevance 6%]

* Re: How can I declare a collection of an interface?
  2013-08-02 16:39  5% How can I declare a collection of an interface? Graham Stark
@ 2013-08-02 16:53  0% ` Eryndlia Mavourneen
  2013-08-02 18:28  6% ` Adam Beneschan
  1 sibling, 0 replies; 200+ results
From: Eryndlia Mavourneen @ 2013-08-02 16:53 UTC (permalink / raw)


On Friday, August 2, 2013 11:39:14 AM UTC-5, Graham Stark wrote:
> Hi,
>    if I have (say):
> 
> type Person is interface;
> 
> and I want to declare a collection of Person, how can I declare the type I'd need? I've tried:
> 
> type PA is array(1..2) of Person;
> 
> or
> 
> package PV is new Ada.Containers.Vectors( Positive, Person );
> 
> and the same with 'Class.
> 
> Graham

An "interface" type is an abstract type, so objects can not be declared using it.  You need to declare a derived type:

   type Human is new Person with ...;
   type HA is array(1..2) of Human;

-- Eryndlia (KK1T)

^ permalink raw reply	[relevance 0%]

* How can I declare a collection of an interface?
@ 2013-08-02 16:39  5% Graham Stark
  2013-08-02 16:53  0% ` Eryndlia Mavourneen
  2013-08-02 18:28  6% ` Adam Beneschan
  0 siblings, 2 replies; 200+ results
From: Graham Stark @ 2013-08-02 16:39 UTC (permalink / raw)


Hi,
   if I have (say):

type Person is interface;

and I want to declare a collection of Person, how can I declare the type I'd need? I've tried:

type PA is array(1..2) of Person;

or

package PV is new Ada.Containers.Vectors( Positive, Person );

and the same with 'Class.

Graham

^ permalink raw reply	[relevance 5%]

* Re: orthogonal inheritance and extension aggregates
  @ 2013-07-19 19:05  7% ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2013-07-19 19:05 UTC (permalink / raw)


On Fri, 19 Jul 2013 19:46:38 +0200, Felix Krause wrote:

> I try to implement some feature via orthogonal inhertance like this:
> 
>     generic
>        type Parent (<>) is abstract tagged private;
>     package Extension is
>        type Extended is abstract new Parent with private;
> 
>        -- operations of the extended type here
>     private
>        type Extended is abstract new Parent with record
>           -- …
>        end record;
>     end Extension;
> 
> Now for testing, I tried to apply this on a Vector:
> 
>     package Int_Vectors is new Ada.Container.Vectors (Natural, Integer);
>     package Base is new Extension (Int_Vectors.Vector);
> 
>     type Child is new Base.Extended with null record;
> 
> At the declaration of Child, GNAT tells me "type must be declared 
> abstract or "To_Vector" overridden". Can someone explain why this 
> happens? As I understand it, To_Vector should be automatically defined 
> for the derived type. Is this because the intermediate type Extended is 
> declared abstract? Or because To_Vector dispatches in the return type?
> 
> Anyway, I tried to declare the function for the type Child like this:
> 
> 
>     function To_Vector (Length : Ada.Containers.Count_Type) return Child is
>     begin
>        return Child'(Base.Extended'(Int_Vectors.To_Vector (Length) with 
> others => <>) with null record);
>     end To_Vector;
> 
> Firstly, this looks rather awkward. Secondly, it doesn't compile: 
> "expected private type Extended […] found a composite type". I guess 
> this does not work because the type Extended is hidden in the private 
> part of Extension. Is it possible to define To_Vector in this context 
> to do exactly what the base function does?

OK here are two different issues.

1. There are more than one To_Vector declared in Ada.Containers.Vectors.
And there are other primitive operations there you must override:

with Ada.Containers.Vectors;
with Extension;
package PE is
    package Int_Vectors is new Ada.Containers.Vectors (Natural, Integer);
    package Base is new Extension (Int_Vectors.Vector);

    type Child is new Base.Extended with null record;
    overriding
       function To_Vector (Length : Ada.Containers.Count_Type) return
Child;
    overriding
       function To_Vector
                (  New_Item : Integer;
                   Length   : Ada.Containers.Count_Type
		)  return Child;	   
    overriding
       function "&" (Left : Child; Right : Child) return Child;
    overriding
       function "&" (Left : Integer; Right : Child) return Child;
    overriding
       function "&" (Left : Child; Right : Integer) return Child;
    overriding
       function "&" (Left, Right : Integer) return Child;	   
    overriding
       function Copy
                (  Source : Child;
                   Capacity : Ada.Containers.Count_Type := 0
                )  return Child;
end PE;

2. This is a more serious problem. You use a private extension in
Extension, which means that clients cannot use aggregates in order to
create instances.

Extension aggregates is a horrific thing in Ada. But nothing compared to
the constructing function.

At this point you must consider what are you going to fight. If aggregates,
then make extension public. If functions then provide a constructing
function in the Extension package.

Beware that your case will be a *combination* of aggregates and
constructing functions is totally broken in Ada. It might happen to work to
you or not. Nobody, even a language lawyer could say in advance if and when
it will.

P.S. I don't know if Ada 2012 silently inherits from null extension. I
heard that there was an intention to add the kludge. Though semantically
broken it would save programs like yours.

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


^ permalink raw reply	[relevance 7%]

* Re: Thick bindings to a C library and gnattest: suggestions?
  @ 2013-07-01 17:16  4% ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2013-07-01 17:16 UTC (permalink / raw)


On 07/01/2013 02:02 AM, ziotom78@gmail.com wrote:
>
> First question: the vectors used by the CFITSIO library are sometimes
> huge (millions of elements), sometimes very small (~ 10 elements).
> I decided to always allocate them on the heap, using declarations like
> these:
>
>     subtype Double is Interfaces.C.double;
>     type Double_Array is array (Positive range <>)
>       of Interfaces.C.double;
>     pragma Convention (C, Double_Array);
>     type Double_Array_Ptr is access Double_Array;
>
> (similar declarations exist for arrays of integers/long...), and then
> using "new Double_Array" whenever I need to allocate room for an
> array. Every binding function only uses Double_Array_Ptr. Is this the best
> way to do this in Ada? Every text I read about Ada says to stay away
> from objects allocated on the heap, but I do not see any other
> solution here.

One should not use heap allocation unnecessarily, as it requires memory 
management, which is often complex and error prone, but that does not mean one 
should never use heap allocation. When it is necessary, there is no alternative. 
What one should not do is have visible access types in public package specs.

As others have pointed out, generally the application is what knows the sizes of 
the objects it works on, and that decides whether heap allocation is required.

I would not use "_Array" in type names. We know it's an array because the type 
declaration says so. The type name should indicate its intended meaning or use, 
not its implementation.

Another approach not mentioned is the use of Ada.Containers.Vectors. This 
implements unbounded arrays. Internally, the arrays are allocated on the heap 
and memory managed, but this complication is hidden from the user. Ada 12 
provides the ability to use them like an array (use of those features currently 
limits you to a single compiler, though).

(Aside: in a world in which GB of RAM are common, it seems odd for a language to 
require explicit heap allocation, and the associated memory management, for 
objects that fit in memory, but not in the stack. Surely it would be better for 
the language to allow the developer to simply declare the object, and for the 
compiler to decide where it will fit, and allocate it and manage its memory 
appropriately. A means to disable automatic heap allocation would be needed for 
systems that disallow heap allocation.)

-- 
Jeff Carter
"Hold your temper. Count ten.... Now let 'er go.
You got a good aim."
Never Give a Sucker an Even Break
105


^ permalink raw reply	[relevance 4%]

* Re: Is this expected behavior or not
  @ 2013-04-02 21:54  2%                                                           ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2013-04-02 21:54 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:3gv2jwc95otm.pl2aahsh9ox8.dlg@40tude.net...
> On Mon, 1 Apr 2013 19:40:42 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net...
>> ....
>>> The point is that whether you create a totally new string hierarchy or
>>> create one for already existing string types, you will have the issue 
>>> with
>>> "&" (and any other operation with more than one argument/result of 
>>> string
>>> type). That is *independent* on whatever Ada did or not before. It is in
>>> the nature of a multi-method, which "&" is. If you want a hierarchy of
>>> strings you *must* face this problem.
>>
>> No you don't. There are no language-defined multi-methods. String & 
>> String =
>> String is not a multi-method.
>
> Once String becomes member of a class it is. For the operation "&" there
> exist only two possibilities, Either it is a primitive operation of the
> class and so a multi-method, or else it is declared individually on each
> member of the class in separate packages (somewhere after the freezing
> point). The later variant is so silly that I don't even consider it.

I agree that latter variant is silly, but the notion that somehow "&" 
becomes a multi-method simply because it exists makes no sense. "=" is not a 
multi-method in Ada today for tagged types; "&" would work the same way - it 
does not take items of different types unless you explicitly convert them. 
Maybe you have a different idea of a multimethod than I do??

>> You, the user, can define such operations, of
>> course, but then you have the deal with the consequences. Generally, it's
>> best if you don't do that.
>
> What is the use of a string type without operations?

Huh? There are predefined single-type operations. If you want mixed type 
operations, you have to define them, but it's usually a bad idea to do so. 
You're almost always better off with 'Class operands if you need type 
mixing -- for type resolution reasons (not even mentioning runtime issues).

...
> You said that it would not fit into Ada 83 derived types model. I answered
> that it never considered within that model. The model to augment is Ada 95
> tagged types.

Tagged types need no augmentation -- they only work because they are 
by-reference types. They can't work without that, and you (rightly) want to 
get rid of that.

>> You have to be able to inherit
>> implementation of operations, for all types.
>
> It is already not so. See Ada 95 abstract primitive operations and
> operations dispatching in the result. They are NOT inherited. The
> programmer is asked to override them, because the compiler has no idea how
> to implement them.

Abstract operations have no implementation to override. Constructor 
functions are a special case where you would never want to share the 
implementation anyway. The fact that other functions aren't extended is a 
mistake in Ada, it makes it impractical to have those in your interfaces.

The Claw Builder has types with a lot of functions and abstract routines, 
and the net effect is that it takes a week or more to create a single 
extension of the type - just to type in all of the bodies required. And the 
result of that is that extensions simply don't get built because the burden 
is too high.

>> And there exist plenty of Ada
>> types for which copying is not allowed.
>
> No problem. See above. All primitive operation will be inherited abstract
> if the representation is not inherited and no [user-defined] conversion
> defined (e.g. for a by-reference type).

That was a bad idea for Ada 95 (there are pretty severe visibility issues 
associated with it), and I don't think it can be extended. In any case, that 
extends the problem of creating extensions -- it would be so diifficult and 
time-consuming that it almost never would be done. (Imagine extending 
Ada.Containers.Vectors if every routine became abstract. You'd never bother, 
because the effort to even write something to compiler would be so extreme. 
It's the exact opposite of agile programming [the only sane way to program, 
IMHO].

>> The only way to implement those is
>> via some sort of dispatching, and the need poisons the possibility of
>> omitting tags, even for "specific" operations.
>
> I don't understand where you get this. The model is exactly the model of
> tagged types, but without specific objects required to keep the tag. The
> only thing it influences is view conversions between T and T'Class. 
> Nothing
> else is changed.

When you dispatch to an inherited routine, you directly call that routine 
with the operands view converted (which cannot make copies in the general 
case). The only way for this to work is for the low-level operations of the 
type to be implemented with dispatching calls -- this is exactly how generic 
units work in Janus/Ada. This requires a descriptor of some sort with every 
object and has the effect of re-dispatching.

You are suggesting making such operations illegal (no inheritance), which 
does eliminate that problem but would make the resulting language 
unusable -- certainly in an agile sense. (The average private type having 
more than 100 operations once inherited and low-level ones that you want to 
break out are included.)

>> The type conversions are view conversions, and they never make copies.
>
> View conversions will be kept for tagged types and not introduced for
> untagged ones.

Untagged types already have view conversions (it's what you pass to "in out" 
parameters in calls). You're 20 years too late with that idea.

>> That
>> forces the representation to be compatible. You could change that for
>> by-copy types (although that would have run-time compatibility issues for
>> controlled objects),
>
> Controlled objects are tagged, hence no change here.

A component is an object; I'm talking about untagged objects with controlled 
components here.

>> but you can't change that for types that have no copy
>> operation (like tasks and protected objects). So how to do you implement
>> them? Array of task is an untagged type, too, and it certainly should be
>> able to use 'Class.
>
> Sure. T'Class will be a referential object when T is untagged by-reference
> type. It will consist of the type tag and a *pointer* to the specific
> object (not much different from 4.1.5), and from view conversions ether,
> though formally a new object.
>
> When T is by-copy, T'Class is the type tag + a copy of T.

Wow! And this is supposed to be a *simplification*??? :-)

>>> I don't ban inheritance of the representation. I want to be able not to 
>>> do
>>> it when I don't need it, e.g. for character and string types.
>>
>> But it's not that easy. If you have an array of tasks:
>>
>>     type Foo (1 .. 10) of Some_Task with Component_Size => 32;
>>
>> and you derive another array of tasks from it:
>>
>>    type New_Foo is new Foo with Component_Size => 64;
>>
>> This is legal, and you have different representations.
>
> Irrelevant. Ada 83 derivation (cloning) is orthogonal to Ada 95 extension
> model. We are talking about the later.

Actually, there is only one model of inheritance in Ada. We're not making 
another one! There are slight differences in how the inheritance happens, 
but it's minor. In any case, there is no reason to separate derived from 
anything else: "type cloning" and "extension without new components" are the 
same thing -- you get a new type that's related to the current one only via 
explicit conversion and class-wide operations.

>>>> It really kills the entire idea.
>>>
>>> No, IF String inherited the representation of Wide_Wide_String, THAT 
>>> would
>>> kill the idea.
>>>
>>> The whole idea is not to inherit irrelevant representations!
>>
>> I don't see the problem here; if Root_String is an abstract tagged type,
>
> Java interfaces will not work for characters/strings. No need even to try
> it.

Java interfaces will not work for anything. No need to even try. :-) And 
who's talking about Java, anyway?

I'm interested in what we can do with tagged types. Forget the silly 
interfaces, or call it an interface if that makes people feel better (that's 
what we did with iterators, but it doesn't actually buy you anything). It's 
an Ada 95 abstract type.

...
>> That would get you a repremand if you worked for me. You never, ever use 
>> the
>> types in Standard (because they're not necessarily portable to other
>> compilers). You derive types based on your actual application 
>> requirements:
>>
>>    type Velocity is digits 5 range -1.0E+10 .. 1.0E+10;
>
> This is a bad design pattern because it refers to some magic numbers 
> spread
> all over the source code, a huge maintenance problem, potentially.

People how spread "magic numbers" all over the source code are idiots. In a 
real program, these would be constants declared in an appropriate package. 
That's Ada 101. I'm not putting that sort of organization in little 
examples, I would hope that is a given around here.

> The proper pattern would be:
>
>   type Measurement is digits 5 range -1.0E+10 .. 1.0E+10;
>   ...
>   type Velocity is new Measurement;
>   type Acceleration is new Measurement;
>   ...

This is a terrible design pattern because it puts unrelated types together 
(and, allows them to be converted to a common ancestor, which almost always 
is a bug - especially if we had Measurement'Class). If I find that in our 
code somewhere, I'm going to remove it and try to find the offending 
programmer for an educational moment. :-)

>>>> Because you need operations that work on every object,
>>>> copyable or not. Remember, there are no type conversions between types 
>>>> in
>>>> different hierarchies.
>>>
>>> And, this is what different hierarchies are for.
>>
>> For what? To make it impossible to pass integers to Text_IO, or to use 
>> them
>> to instantiation Text_IO?
>
> It is in the same generic formal class, thus instantiation is possible.

The "generic formal class" = hierarchy in Ada; if you split the hierarchy, 
then it's no longer in the same formal class. (That's the *meaning* of 
"class" in Ada; if you wanted truly unrelated things to work, it would have 
to be a "category" instead -- but there are no shared operations for 
categories as that does not make sense. And "categories" are never 
inherited.)

> You are confusing generic classes, and classes induced by cloning, and
> classes induced by interface inheritance. They are not same.

I'm not confusing anything -- they *are* the same thing in Ada. I suppose 
you could introduce a whole new boatload of complexity to the language 
definition to make them different, but how you can call that a 
simplification is beyond me.

> There is an infinite number of means by which some types could be lumped
> into a class. Class is no more than a set of types. E.g. all types which
> declarations start at the source code line 123 is a class. That does not
> make them possible or not to be used in Text_IO instantiation. That would
> be some other class.

No, that's a "category" (in Ada terminology). Limited types are a 
"category", because that's not an inherited property. "Class" is always 
inherited: all members of a hierarchy rooted at a class have the same 
properties.

>>>>> But they are still the same
>>>>> hierarchy. You need some fundamental operation which tells that a type
>>>>> breaks off the hierarchy.
>>>>
>>>> Yes, of course all containers ought to be members of the same 
>>>> hierarchy.
>>>> How else would you create generic algorithms?
>>>
>>> Easily. Cloning borrows all operations. Define algorithm on the original
>>> type. Then clone it. Done!
>>
>> But you have cloned nothing.
>
> I did types, literals, operations.
>
>> Either you have a conversion to the original
>> type, in which case they belong to the same hierarchy.
>
> This is a possible way to implement cloning. This is not the semantics of.
> The semantics is that there is a new set of types, values and operations
> with the properties of the original. Nothing more.

If they allow conversion (including implicitly to the class-wide root of the 
class) and instantiation, they're members of the same hierarchy. So it's the 
same as any other kind of extension inheritance (essentially a null 
extension). If it *doesn't* allow conversion and instantiation, then it's 
pretty useless (and it's not the same as Ada is today, which you claim you 
want to support).

You do know that there are special rules for null extension so that you 
don't have to override any functions returning the type? Unlike normal 
extension, you only have to override abstract operations (which there should 
be none). So there would be no semantic difference between writing (if you 
could):
    type T is new W;
and (which you can write):
    type T is new W with null record;

I'm not actually sure why the former is disallowed, I think it's an intent 
to highlight the difference between tagged and untagged types. (And I don't 
know why we would want to highlight that!)

>> A string class with a mixed & is nonsense. (I think the String & 
>> Character
>> in Ada 83 was nonsense, but it's not a problem here.)
>
> It would be interesting to learn how many c.l.a. readers share such an
> extreme view.
>
> To me "&" is one of the most important requirements on string class 
> design.
> It is also a good test for the language type system maturity.
>
>> The only & is String & String = String, and so on for all types.
>
> Totally useless, IMO.

Fair enough, we can agree to disagree on all of this. That's how Ada works 
today, and I've hardly ever heard anyone claim that Ada array types are 
"totally useless".

                                    Randy.





^ permalink raw reply	[relevance 2%]

* Re: Is this expected behavior or not
  2013-03-28 13:50  0%                                             ` Dmitry A. Kazakov
@ 2013-03-28 21:55  0%                                               ` Randy Brukardt
    0 siblings, 1 reply; 200+ results
From: Randy Brukardt @ 2013-03-28 21:55 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:cqf0yy6q930$.1sdzw45bc0c1w.dlg@40tude.net...
> On Wed, 27 Mar 2013 14:42:47 -0500, Randy Brukardt wrote:
>
>> The problem is that a slice ought to be a referential object as you put 
>> it,
>> and a "regular" object is definitely *not* a referential object (a copy
>> copies the data).
>
> What is "regular" object here? String?

A non-slice string object.

>> I don't see any way for a single data type to have two
>> different behaviors
>
> These are two data types, string and slice. Are you treating slice as an
> Ada-subtype of string? I consider slice a member of same class as string,
> yet a distinct type (in Ada sense). This is like 4.1.5, but in the same
> type hierarchy.

I thought you might do that, but then you're going to have problems of 
compatibility (Ada currently considers them the same type). An operation 
like "&" cannot not allow mixed string operands (if you do allow that, you 
make string literals ambiguous).

...
>> Nobody wants "type cloning".
>
> It is a very useful building block to me. Anyway it is Ada 83 legacy.

Ada 83 derived types are virtually useless, and no one understood how they 
worked. I objected to building tagged types on that foundation during Ada 
9x, but they didn't pay any attention to me on that. :-)

Ada 83 derived types would be one of the first things to get rid of in a new 
Ada-like language -- everything should be related. Indeed, all integer types 
belong to Root_Integer'Class (you just can't name that type in Ada as it 
stands); it would be weird to *break* that.

 ...
>> I don't think a version of untagged'Class that did not work on existing
>> derived types would fly.
>
> Astonishing that you even considered that possibility. In my view they are
> completely independent things.

You really have a strange mind. The whole idea of 'Class is to allow 
different but related types to share implementations. You're only allowed to 
convert between related types, which includes derived types.

>> In any case, I didn't realize that you were making an entire new kind of
>> type derivation
>
> To me it is exactly same as tagged extension when you add nothing to the
> existing representation.

Sure, this I totally agree with. But those are highly related to each other: 
Parent'Class includes the parent and the derivation.

> We also need "extension" that drops parent's representation altogether.
> E.g. something like:
>
>   type Character is new Unsigned_8 -- or enumeration, whatever
>      and Wide_Wide_Character'Interface;
>
> Character is member of Wide_Wide_Character'Class with a representation
> different from Wide_Wide_Character.

I don't think that would work semantically, at least in the 'Class case. 
Unless you expect every operation down to assigning individual components to 
be dispatching, even in primitive routines defined for a specific type. 
That's because you can't copy all tagged types (we have to have limited 
types), and thus calling a parent operation would have to assume that 
extensions have a different representation. That would both have problems of 
re-dispatch and simply would be awfully expensive (you'd have to do full 
program compilation to have any hope of decent code).

The only alternative would be to totally ban implementation inheritance on 
such types, but as implementation inheritance is 10 times more useful than 
interface inheritance, it would make the construct 95% useless.

>>> Moreover, it is highly desired to that cloning were available for tagged
>>> types as well:
>>>
>>>   package Original is new Ada.Containers.Vectors ...;
>>>   type Clone is new Original.Vector; -- Cloning, not extending!
>>>
>>> Now, I have to hierarchies of Vector, not very useful in this particular
>>> case, because of missing helper types, but anyway.
>>
>> Pointless complication. I thought you were trying to simplify the 
>> language!
>
> Making it regular is a simplification.

This isn't regular. All numeric types are currently members of a single 
hierarchy, and in practice, the vast majority of tagged types are members of 
two hierarchies (controlled and limited controlled). If I was going to 
simplify this further, I would make all of these into a single hierarchy. 
More hierarchies don't buy anything (you can always move your 'Classes 
around in the hierarchy to get subsets).

>>>>      overriding
>>>>      procedure Op (A : in out Der; B : in Der);
>>>
>>> This is not an overriding since the mode is different.
>>
>> It *is* an overriding in Ada 83, and it still is in Ada 2012. I agree 
>> that
>> it should not have been, but that is irrelevant because we're stuck with 
>> it.
>
> Only when Der is derived using Ada 83 construct. Int'Class will be built
> using "extension."

No way; derived types currently form a hierarchy (that's why you can 
interconvert them); changing that would require fundamentally changing the 
Ada model of hierarchies. The issue today is that you can't name those 
hierarchies, that's what untagged 'Class would allow.

>>>>      Obj : Int'Class := Der'(1);
>>>>      Op (A => 1, B => Obj); -- Legal??
>>>
>>> MD is not fully implemented in Ada, but anyway, presuming that Op is a
>>> multi-method, that the mode is "in" and that 1 is Universal_Integer (is
>>> it?), the above is illegal because Op is not a method of
>>> Universal_Integer'Class. You would have to write it as:
>>>
>>>   Op (A => Der'(1), B => Obj);  -- Same tags
>>>   Op (A => Int'(1), B => Obj);  -- Different tags, Constraint_Error
>>
>> This seems wrong; an integer literal usually gets its type from context.
>> It's only a value of type Universal_Integer if there is no type given 
>> from
>> context (as in a type conversion or number declaration). I was presuming
>> that integer literals act as tag-indeterminate functions (the most 
>> sensible
>> model; if you have constants for a tagged type you usually would model 
>> them
>> as tag-indeterminate functions - for instance, the constants Zero and One 
>> in
>> a universal arithmetic package), you don't need multiple dispatch: the 
>> Ada
>> dispatching rules simply calls the correct version of the function for 
>> the
>> tag of the object. And that's what we would want to happen for integer
>> literals (that's the closest analogy to what happens for existing
>> expressions).
>
> This is one of possible interpretations of Ada semantics. You consider
> literals primitive operations, e.g.
>
>   function "1" return Int;
>
> In Ada 95 such function has to be overridden, when Der extends Int.
> However, if the representation is inherited and not changed, the rule 
> could
> be that the compiler silently overrides all literals:
>
>   overriding function "1" return Der;
>
> In this case you will have 1 overloaded. Op will become ambiguous.

Yes, this is how Ada literals work today. This isn't how its described (it's 
an implicit conversion rather than overloading) but the effect is the same.

> The alternative with different types can be discarded using some 
> preference
> rules, e.g. domination, and thus ambiguity resolved.

Preference rules cause Beaujolias effects, and almost never can be 
tolerated. Ada used to have some for literals and they caused all manner of 
problems. The preference rules for universal causes problems as well (as you 
are pointing out here); these are extremely fragile and only work because 
universal types can't have any user-defined operations or visibility 
changes.

As soon as user-defined things are involved, preference rules simply don't 
work. Maybe they would work in a language without nesting and private parts 
and use clauses, but they don't work in Ada. (The problem being that adding 
or removing a single declaration can silently change the meaning of an 
expression without causing an error. This is considered intolerable.)

>>>> An interface can't have "..." as the parameter type for Write; there 
>>>> has
>>>> to be something there.
>>>
>>>   procedure Write (File : in out File_Access; Data : 
>>> Stream_Element_Array)
>>>      is abstract;
>>>
>>>> And that's the target type! Say again how it is that you
>>>> are not exposing this type??
>>>
>>> The target is File. I would gladly have MD and a hierarchy for the 
>>> second
>>> parameter, but that is another story for now.
>>
>> OK, if the target is File, then you know that - that's public 
>> information.
>> When you dereference a File_Handle, you get a File. You don't have to 
>> make
>> the contents of File public, just it's name. So I still don't see why you
>> think this is a problem.
>
> I don't want to expose File at all. Public views should have no access to
> it, otherwise than indirectly through the handle. E.g. they should not be
> able to get an access the file object, store it somewhere, deallocate it,
> use stream attributes on it, and perform any other fancy stuff.
> Furthermore, later on, a decision may fall to replace file descriptor with
> something completely different keeping code that uses handles intact. It 
> is
> good old information hiding principle.

Fine. But then you don't need any user-visible dereferencing, and you surely 
wouldn't use it. My contention remains: if you are going to allow user 
"Handle.all", then you need to expose the type of Handle.all. If you don't 
need to allow that, then you are not going to use 4.1.5 at all. So I fail to 
see your concern.

>>> Because whether a message is relevant to the choice if the program were 
>>> OK
>>> to deploy depends now on the message content. The language does not help
>>> me anymore to indicate it as a bug.
>>
>> But there is absolutely nothing new about this.
>
> There is nothing new that people die, yet nobody actually likes it.
>
>> GNAT has a variety of
>> warnings (calling everything it displays a "warning" in order to avoid
>> arguments about its particular classifications of message), but most 
>> people
>> choose to treat some subset of them as errors that have to be removed 
>> before
>> deployment. You would do that same; choose a *class* of warnings that 
>> have
>> to be removed; there is no parsing of messages needed. If a warning in 
>> the
>> prohibited class exists, the program is not ready for deployment.
>
> Some C compilers give warning when you write:
>
>   if (x = 1) ...
>
>> Yes, this means you need to develop a coding standard and a development
>> standard to ensure that these these things are followed. But not having
>> those in some form is just lousy programming management.
>
> Error checks do not belong to coding standards. Coding standard, and
> testing, and code review etc are there when compiler checks were
> impossible.

Compiler checks are impossible for these things. Unless you want to drive 
yourself nuts with OOP baloney - and it's never going to be possible to do 
these sorts of checks with type checking. (This is not a type problem, it's 
a subtype (in the Ada sense) problem.) Feel free to pick your poison, as it 
will, but expecting types to do all of the work is just as silly as 
expecting that you can make a correct program with defining any types at 
all.

                                       Randy.





^ permalink raw reply	[relevance 0%]

* Re: Is this expected behavior or not
  2013-03-27 19:42  0%                                           ` Randy Brukardt
@ 2013-03-28 13:50  0%                                             ` Dmitry A. Kazakov
  2013-03-28 21:55  0%                                               ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2013-03-28 13:50 UTC (permalink / raw)


On Wed, 27 Mar 2013 14:42:47 -0500, Randy Brukardt wrote:

> The problem is that a slice ought to be a referential object as you put it, 
> and a "regular" object is definitely *not* a referential object (a copy 
> copies the data).

What is "regular" object here? String?

> I don't see any way for a single data type to have two 
> different behaviors

These are two data types, string and slice. Are you treating slice as an
Ada-subtype of string? I consider slice a member of same class as string,
yet a distinct type (in Ada sense). This is like 4.1.5, but in the same
type hierarchy.

>>> You missed the point altogether. You can't dispatch in general on untagged
>>> types because overriding operations may have different modes and subtypes
>>> for the parameters. So what *is* the profile of the operation for T'Class,
>>> and how can it work?
>>>
>>> Consider:
>>>
>>>      Type Int is range 1 .. 10;
>>>      procedure Op (A, B : in Int);
>>>
>>>      Type Der is new Int;
>>
>> This is not derivation within the class, it is a "type-cloning." Type
>> cloning creates a new class and new a type (all types up the hierarchy). 
>> We need some syntax to indicate the difference.
>>
>>   type Der is new Int <whatever>;
>>
>> It is unfortunate that tagged types reused "is new" for a purpose
>> completely different from type cloning.
> 
> Nobody wants "type cloning".

It is a very useful building block to me. Anyway it is Ada 83 legacy.

> I have no idea why anyone that wants 'Class 
> would want to avoid maximizing the interoperability of types.

Sometimes we want types related, sometimes we don't, while reusing existing
implementations. The language should support programmer's choice.

> The original motivating example for Integer'Class was:
> 
>      Put (Obj : Integer'Class; Width : Count := 0);
> 
> so that one didn't need to understand generic instantiations just to do 
> simple I/O of strongly typed entities.

Yes.

Cloned Integer will "inherit" this Put operation in Ada 83 sense. Ada 83
cloning is orthogonal to type hierarchies. You get a new hierarchy when you
clone a type.

> I don't think a version of untagged'Class that did not work on existing 
> derived types would fly.

Astonishing that you even considered that possibility. In my view they are
completely independent things.

> In any case, I didn't realize that you were making an entire new kind of 
> type derivation

To me it is exactly same as tagged extension when you add nothing to the
existing representation.

We also need "extension" that drops parent's representation altogether.
E.g. something like:

   type Character is new Unsigned_8 -- or enumeration, whatever
      and Wide_Wide_Character'Interface;

Character is member of Wide_Wide_Character'Class with a representation
different from Wide_Wide_Character.

>> Moreover, it is highly desired to that cloning were available for tagged
>> types as well:
>>
>>   package Original is new Ada.Containers.Vectors ...;
>>   type Clone is new Original.Vector; -- Cloning, not extending!
>>
>> Now, I have to hierarchies of Vector, not very useful in this particular
>> case, because of missing helper types, but anyway.
> 
> Pointless complication. I thought you were trying to simplify the language!

Making it regular is a simplification.

>>>      overriding
>>>      procedure Op (A : in out Der; B : in Der);
>>
>> This is not an overriding since the mode is different.
> 
> It *is* an overriding in Ada 83, and it still is in Ada 2012. I agree that 
> it should not have been, but that is irrelevant because we're stuck with it.

Only when Der is derived using Ada 83 construct. Int'Class will be built
using "extension."

>>>      Obj : Int'Class := Der'(1);
>>>      Op (A => 1, B => Obj); -- Legal??
>>
>> MD is not fully implemented in Ada, but anyway, presuming that Op is a
>> multi-method, that the mode is "in" and that 1 is Universal_Integer (is
>> it?), the above is illegal because Op is not a method of
>> Universal_Integer'Class. You would have to write it as:
>>
>>   Op (A => Der'(1), B => Obj);  -- Same tags
>>   Op (A => Int'(1), B => Obj);  -- Different tags, Constraint_Error
> 
> This seems wrong; an integer literal usually gets its type from context. 
> It's only a value of type Universal_Integer if there is no type given from 
> context (as in a type conversion or number declaration). I was presuming 
> that integer literals act as tag-indeterminate functions (the most sensible 
> model; if you have constants for a tagged type you usually would model them 
> as tag-indeterminate functions - for instance, the constants Zero and One in 
> a universal arithmetic package), you don't need multiple dispatch: the Ada 
> dispatching rules simply calls the correct version of the function for the 
> tag of the object. And that's what we would want to happen for integer 
> literals (that's the closest analogy to what happens for existing 
> expressions).

This is one of possible interpretations of Ada semantics. You consider
literals primitive operations, e.g.

   function "1" return Int;

In Ada 95 such function has to be overridden, when Der extends Int.
However, if the representation is inherited and not changed, the rule could
be that the compiler silently overrides all literals:

   overriding function "1" return Der;

In this case you will have 1 overloaded. Op will become ambiguous. The
alternative with different types can be discarded using some preference
rules, e.g. domination, and thus ambiguity resolved.

>>> An interface can't have "..." as the parameter type for Write; there has 
>>> to be something there.
>>
>>   procedure Write (File : in out File_Access; Data : Stream_Element_Array)
>>      is abstract;
>>
>>> And that's the target type! Say again how it is that you
>>> are not exposing this type??
>>
>> The target is File. I would gladly have MD and a hierarchy for the second
>> parameter, but that is another story for now.
> 
> OK, if the target is File, then you know that - that's public information. 
> When you dereference a File_Handle, you get a File. You don't have to make 
> the contents of File public, just it's name. So I still don't see why you 
> think this is a problem.

I don't want to expose File at all. Public views should have no access to
it, otherwise than indirectly through the handle. E.g. they should not be
able to get an access the file object, store it somewhere, deallocate it,
use stream attributes on it, and perform any other fancy stuff.
Furthermore, later on, a decision may fall to replace file descriptor with
something completely different keeping code that uses handles intact. It is
good old information hiding principle.

>> Because whether a message is relevant to the choice if the program were OK
>> to deploy depends now on the message content. The language does not help 
>> me anymore to indicate it as a bug.
> 
> But there is absolutely nothing new about this.

There is nothing new that people die, yet nobody actually likes it.

> GNAT has a variety of 
> warnings (calling everything it displays a "warning" in order to avoid 
> arguments about its particular classifications of message), but most people 
> choose to treat some subset of them as errors that have to be removed before 
> deployment. You would do that same; choose a *class* of warnings that have 
> to be removed; there is no parsing of messages needed. If a warning in the 
> prohibited class exists, the program is not ready for deployment.

Some C compilers give warning when you write:

   if (x = 1) ...

> Yes, this means you need to develop a coding standard and a development 
> standard to ensure that these these things are followed. But not having 
> those in some form is just lousy programming management.

Error checks do not belong to coding standards. Coding standard, and
testing, and code review etc are there when compiler checks were
impossible.

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

^ permalink raw reply	[relevance 0%]

* Re: Is this expected behavior or not
  2013-03-27  9:37  3%                                         ` Dmitry A. Kazakov
@ 2013-03-27 19:42  0%                                           ` Randy Brukardt
  2013-03-28 13:50  0%                                             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Randy Brukardt @ 2013-03-27 19:42 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:wdlyfbnwcnp7.10c9btwjmpm7j.dlg@40tude.net...
> On Tue, 26 Mar 2013 16:31:35 -0500, Randy Brukardt wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:1u72u7h5j4jg3$.wlxmaltyzqik.dlg@40tude.net...
>>> On Mon, 25 Mar 2013 17:58:26 -0500, Randy Brukardt wrote:
>>>
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>>> news:a96esjwiniqy$.op3wh7x9wrsl.dlg@40tude.net...
>>>>> On Fri, 22 Mar 2013 21:33:02 -0500, Randy Brukardt wrote:
>>>> ...
>>>>>> That doesn't necessarily mean copying of the data. If the designer
>>>>>> of the abstraction, have put in enough smarts to share
>>>>>> representations --
>>>>>> after all,
>>>>>
>>>>> You should break your mental block. No shared representation, I want
>>>>> different representations for different string types.
>>>>
>>>> I was talking about sharing representations of *different* objects of 
>>>> the
>>>> same string type (for instance, a string variable and a slice of that
>>>> variable - that case, sharing the data might be preferred to copying 
>>>> it).
>>>
>>> OK, the representation would be for type-specific string objects:
>>>
>>>   bounds + pointer
>>>
>>> and for class-wide string objects:
>>>
>>>   tag + bounds + pointer
>>
>> Sure, but irrelevant. The question is whether slicing copies the data or
>> not. If it is a new object, the data must be copied logically,
>
> No, logically it is a referential object.
>
>> but my point
>> was that it would be possible for an abstraction to defer actually making 
>> a
>> copy until an assignment is actually done. It's still a copy.
>
> Exactly the reverse, an implementation could be allowed to use a copy if
> that is consistent with the semantics of the slice being a reference.
>
> But regardless of the semantics, why this representation should not work?

The problem is that a slice ought to be a referential object as you put it, 
and a "regular" object is definitely *not* a referential object (a copy 
copies the data). I don't see any way for a single data type to have two 
different behaviors - as you've argued elsewhere, you can't have a single 
operation doing two different things. I suppose you could make a slice be a 
different type than a regular string object, but then you have problems with 
type matching (you want a slice to be compatible with the equivalent normal 
object).

...
>>>> And dispatching is incompatible with untagged types, simply because Ada
>>>> 83 got inheritance horribly wrong, and we're stuck with that.
>>>
>>> I disagree. It seems fully compatible with Ada 83 because T'Class would 
>>> be
>>> a distinct type with objects of that type. It is orthogonal to
>>> Ada-subtypes. You will not dispatch on Positive vs. Integer, these will
>>> reman specific [sub]types. In order to dispatch you will need a 
>>> class-wide
>>> object of the type Integer'Class (which will be strictly same as
>>> Positive'Class, except, possibly, the constraint). That object will have
>>> the representation tag + value. For Integer and Positive objects nothing
>>> changes. We might consider redefining some existing operations to become
>>> class-wide in some arguments, but that is another story.
>>
>> You missed the point altogether. You can't dispatch in general on 
>> untagged
>> types because overriding operations may have different modes and subtypes
>> for the parameters. So what *is* the profile of the operation for 
>> T'Class,
>> and how can it work?
>>
>> Consider:
>>
>>      Type Int is range 1 .. 10;
>>      procedure Op (A, B : in Int);
>>
>>      Type Der is new Int;
>
> This is not derivation within the class, it is a "type-cloning." Type
> cloning creates a new class and new a type (all types up the hierarchy). 
> We
> need some syntax to indicate the difference.
>
>   type Der is new Int <whatever>;
>
> It is unfortunate that tagged types reused "is new" for a purpose
> completely different from type cloning.

Nobody wants "type cloning". We waste a lot of mental energy getting rid of 
it in generics, for example. I have no idea why anyone that wants 'Class 
would want to avoid maximizing the interoperability of types. The original 
motivating example for Integer'Class was:

     Put (Obj : Integer'Class; Width : Count := 0);

so that one didn't need to understand generic instantiations just to do 
simple I/O of strongly typed entities.

I don't think a version of untagged'Class that did not work on existing 
derived types would fly. For no other reason than the fact that it would 
make tagged and untagged types more different, rather than less different.

In any case, I didn't realize that you were making an entire new kind of 
type derivation - I wouldn't have guessed that someone that has been talking 
repeatedly about simplifying the language would add an entirely new kind of 
type to the language.

> Moreover, it is highly desired to that cloning were available for tagged
> types as well:
>
>   package Original is new Ada.Containers.Vectors ...;
>   type Clone is new Original.Vector; -- Cloning, not extending!
>
> Now, I have to hierarchies of Vector, not very useful in this particular
> case, because of missing helper types, but anyway.

Pointless complication. I thought you were trying to simplify the language!

>>      overriding
>>      procedure Op (A : in out Der; B : in Der);
>
> This is not an overriding since the mode is different.

It *is* an overriding in Ada 83, and it still is in Ada 2012. I agree that 
it should not have been, but that is irrelevant because we're stuck with it.

>>      Obj : Int'Class := Der'(1);
>>      Op (A => 1, B => Obj); -- Legal??
>
> MD is not fully implemented in Ada, but anyway, presuming that Op is a
> multi-method, that the mode is "in" and that 1 is Universal_Integer (is
> it?), the above is illegal because Op is not a method of
> Universal_Integer'Class. You would have to write it as:
>
>   Op (A => Der'(1), B => Obj);  -- Same tags
>   Op (A => Int'(1), B => Obj);  -- Different tags, Constraint_Error

This seems wrong; an integer literal usually gets its type from context. 
It's only a value of type Universal_Integer if there is no type given from 
context (as in a type conversion or number declaration). I was presuming 
that integer literals act as tag-indeterminate functions (the most sensible 
model; if you have constants for a tagged type you usually would model them 
as tag-indeterminate functions - for instance, the constants Zero and One in 
a universal arithmetic package), you don't need multiple dispatch: the Ada 
dispatching rules simply calls the correct version of the function for the 
tag of the object. And that's what we would want to happen for integer 
literals (that's the closest analogy to what happens for existing 
expressions).

> Multi-methods (a special case of MD) is another and long story. They 
> should
> be properly supported in the end.
>
>> And if you say that Der cannot override Op this way, you're now 
>> incompatible
>> with Ada 83- Ada 2012.
>
> I want to preserve and extend type-cloning.

And you claim that the ARG keeps building gazebos. You're building a 
lakeside floating pavillion. ;-)

...
>> An interface can't have "..." as the parameter type for Write; there has 
>> to
>> be something there.
>
>   procedure Write (File : in out File_Access; Data : Stream_Element_Array)
>      is abstract;
>
>> And that's the target type! Say again how it is that you
>> are not exposing this type??
>
> The target is File. I would gladly have MD and a hierarchy for the second
> parameter, but that is another story for now.

OK, if the target is File, then you know that - that's public information. 
When you dereference a File_Handle, you get a File. You don't have to make 
the contents of File public, just it's name. So I still don't see why you 
think this is a problem.

>>>>>> That's my point about static analysis. Such a tool should be able to 
>>>>>> prove
>>>>>> that the majority of run-time checks can't happen, and give you a 
>>>>>> list of
>>>>>> those remaining.
>>>>>
>>>>> I don't need any list. Should I send it to my customers? I need the
>>>>> program fail to compile when writing analogue input.
>>>>
>>>> Treat the list as failures if you must, and insist that it be empty
>>>> before shipping.
>>>
>>> So, I need an AI system to parse compiler messages (of various vendors) 
>>> on
>>> top?
>>
>> Huh? Why would you "parse" them?
>
> Because whether a message is relevant to the choice if the program were OK
> to deploy depends now on the message content. The language does not help 
> me
> anymore to indicate it as a bug.

But there is absolutely nothing new about this. GNAT has a variety of 
warnings (calling everything it displays a "warning" in order to avoid 
arguments about its particular classifications of message), but most people 
choose to treat some subset of them as errors that have to be removed before 
deployment. You would do that same; choose a *class* of warnings that have 
to be removed; there is no parsing of messages needed. If a warning in the 
prohibited class exists, the program is not ready for deployment.

Yes, this means you need to develop a coding standard and a development 
standard to ensure that these these things are followed. But not having 
those in some form is just lousy programming management. And one thing we 
decided on the ARG long ago is that there is no way that a programming 
language can prevent lousy programming management -- any language can be 
misused without much effort. That cannot be prevented by a programming 
language; it's futile to try, and when you do try, you tend to make the 
language harder to use on real problems. So we assume competent management 
is used with Ada; we're not trying to make the language idiot-proof.

                                            Randy.





^ permalink raw reply	[relevance 0%]

* Re: Is this expected behavior or not
  @ 2013-03-27  9:37  3%                                         ` Dmitry A. Kazakov
  2013-03-27 19:42  0%                                           ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2013-03-27  9:37 UTC (permalink / raw)


On Tue, 26 Mar 2013 16:31:35 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
> news:1u72u7h5j4jg3$.wlxmaltyzqik.dlg@40tude.net...
>> On Mon, 25 Mar 2013 17:58:26 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:a96esjwiniqy$.op3wh7x9wrsl.dlg@40tude.net...
>>>> On Fri, 22 Mar 2013 21:33:02 -0500, Randy Brukardt wrote:
>>> ...
>>>>> That doesn't necessarily mean copying of the data. If the designer
>>>>> of the abstraction, have put in enough smarts to share 
>>>>> representations --
>>>>> after all,
>>>>
>>>> You should break your mental block. No shared representation, I want
>>>> different representations for different string types.
>>>
>>> I was talking about sharing representations of *different* objects of the
>>> same string type (for instance, a string variable and a slice of that
>>> variable - that case, sharing the data might be preferred to copying it).
>>
>> OK, the representation would be for type-specific string objects:
>>
>>   bounds + pointer
>>
>> and for class-wide string objects:
>>
>>   tag + bounds + pointer
> 
> Sure, but irrelevant. The question is whether slicing copies the data or 
> not. If it is a new object, the data must be copied logically,

No, logically it is a referential object.

> but my point 
> was that it would be possible for an abstraction to defer actually making a 
> copy until an assignment is actually done. It's still a copy.

Exactly the reverse, an implementation could be allowed to use a copy if
that is consistent with the semantics of the slice being a reference.

But regardless of the semantics, why this representation should not work?

>>> Unifying old junk it's possible without serious breakage of existing 
>>> code, which is intolerable.
>>
>> Why is it junk? There is nothing wrong with String, Wide_String,
>> Wide_Wide_String. They should stay.
> 
> They're junk because they can't be unified without serious breakage of 
> existing code.

A common ancestor would not break existing code. An ad-hoc ancestor could
not do it even theoretically, because it is limited to the context where
the ancestor is visible.

>>> And dispatching is incompatible with untagged types, simply because Ada 
>>> 83 got inheritance horribly wrong, and we're stuck with that.
>>
>> I disagree. It seems fully compatible with Ada 83 because T'Class would be
>> a distinct type with objects of that type. It is orthogonal to
>> Ada-subtypes. You will not dispatch on Positive vs. Integer, these will
>> reman specific [sub]types. In order to dispatch you will need a class-wide
>> object of the type Integer'Class (which will be strictly same as
>> Positive'Class, except, possibly, the constraint). That object will have
>> the representation tag + value. For Integer and Positive objects nothing
>> changes. We might consider redefining some existing operations to become
>> class-wide in some arguments, but that is another story.
> 
> You missed the point altogether. You can't dispatch in general on untagged 
> types because overriding operations may have different modes and subtypes 
> for the parameters. So what *is* the profile of the operation for T'Class, 
> and how can it work?
> 
> Consider:
> 
>      Type Int is range 1 .. 10;
>      procedure Op (A, B : in Int);
> 
>      Type Der is new Int;

This is not derivation within the class, it is a "type-cloning." Type
cloning creates a new class and new a type (all types up the hierarchy). We
need some syntax to indicate the difference.

   type Der is new Int <whatever>;

It is unfortunate that tagged types reused "is new" for a purpose
completely different from type cloning.

Moreover, it is highly desired to that cloning were available for tagged
types as well:

   package Original is new Ada.Containers.Vectors ...;
   type Clone is new Original.Vector; -- Cloning, not extending!

Now, I have to hierarchies of Vector, not very useful in this particular
case, because of missing helper types, but anyway.

>      overriding
>      procedure Op (A : in out Der; B : in Der);

This is not an overriding since the mode is different.

>      Obj : Int'Class := Der'(1);
>      Op (A => 1, B => Obj); -- Legal??

MD is not fully implemented in Ada, but anyway, presuming that Op is a
multi-method, that the mode is "in" and that 1 is Universal_Integer (is
it?), the above is illegal because Op is not a method of
Universal_Integer'Class. You would have to write it as:

   Op (A => Der'(1), B => Obj);  -- Same tags
   Op (A => Int'(1), B => Obj);  -- Different tags, Constraint_Error

Multi-methods (a special case of MD) is another and long story. They should
be properly supported in the end.

> And if you say that Der cannot override Op this way, you're now incompatible 
> with Ada 83- Ada 2012.

I want to preserve and extend type-cloning.
 
>>>>>> You have a very specific use case in mind, namely containers. There is a
>>>>>> whole world outside that, for which what you said is untrue, e.g. for
>>>>>> smart pointers. The thing not only exposes access, it also exposes the
>>>>>> target type.
>>>>>
>>>>> You have to expose the target type in order to have strong typing. How
>>>>> could you hide it and still make type checks?
>>>>
>>>> Why should target type be public?
>>>
>>> How do you enforce strong typing without that being the case? If you don't
>>> know what the target is, how do you determine how the resulting object can
>>> be used?
>>
>> Target and handle types usually implement some public interface. E.g.
>>
>>   type File_Access is limited interface;
>>   procedure Write (File : in out File_Access; Data : ...) is abstract;
>>   ...
>>
>> Somewhere else
>>
>>   type File_Descriptor is ... limited ... and File_Access ...;
>>
>> Somewhere else
>>
>>   type File_Handle is ... and File_Access ...;
> 
> An interface can't have "..." as the parameter type for Write; there has to 
> be something there.

   procedure Write (File : in out File_Access; Data : Stream_Element_Array)
      is abstract;

> And that's the target type! Say again how it is that you 
> are not exposing this type??

The target is File. I would gladly have MD and a hierarchy for the second
parameter, but that is another story for now.

>>>>> That's my point about static analysis. Such a tool should be able to prove
>>>>> that the majority of run-time checks can't happen, and give you a list of
>>>>> those remaining.
>>>>
>>>> I don't need any list. Should I send it to my customers? I need the
>>>> program fail to compile when writing analogue input.
>>>
>>> Treat the list as failures if you must, and insist that it be empty 
>>> before shipping.
>>
>> So, I need an AI system to parse compiler messages (of various vendors) on
>> top?
> 
> Huh? Why would you "parse" them?

Because whether a message is relevant to the choice if the program were OK
to deploy depends now on the message content. The language does not help me
anymore to indicate it as a bug.

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


^ permalink raw reply	[relevance 3%]

* Re: chopping Ada source that have preprocessor symbols in them
  @ 2013-02-06 12:00  7%   ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2013-02-06 12:00 UTC (permalink / raw)


On 06.02.13 06:29, codeallergy wrote:
> Hi Georg,
>
> gnatchop call gcc with the -gnatu flag to generates the unit separation offsets.

Interesting switch.

> the problem is that the offsets are for the preprocessed file but gnatchop separates the non preprocessed one.
> you could use gnatchop without any preprocessor flags (you will get errors but the file should be cut rightly).

Some parse errors will stop gnatchop, depending on where
the preprocessor symbols are, so I cannot ignore the errors,
unfortunately. I noticed that gnatchop accepts -gnatep
(but not -P, o.K.). Using -gnatep makes the problems appear
exactly as you indicated. Gnatchop cuts the Ada source program
at the wrong offsets. Test case:

$ gnatchop -w -gnatep=multiple_units.ep multiple_units.ada Source
splitting multiple_units.ada into:
    Source/unit_1.ads
    Source/unit_2.ads
    Source/unit_3.ads
$ ls Source/unit_?.ads | while read f ; do cat $f ; echo "<<<*>>>" ; done
package Unit_1 is
    type T is tagged null record;
    procedure Op (Item : T);
end Unit_1;
<<<*>>>

with Unit_1;
$prv with Ada.Containers.Vectors;
package Unit_2 is
    type T is new Unit_1.T with null record;
    $ovr
    procedure Op (Item : T);
private
    package Foo is new Ada.Containers.Vectors (Positive, Character);
end Unit_2;

with Uni<<<*>>>
t_1;
package Unit_3 is
end Unit_3;
<<<*>>>

$ cat multiple_units.ep
* "multiple_units.prep"
$ cat multiple_units.prep
ovr := overriding
prv := private
$ cat multiple_units.ada
package Unit_1 is
    type T is tagged null record;
    procedure Op (Item : T);
end Unit_1;

with Unit_1;
$prv with Ada.Containers.Vectors;
package Unit_2 is
    type T is new Unit_1.T with null record;
    $ovr
    procedure Op (Item : T);
private
    package Foo is new Ada.Containers.Vectors (Positive, Character);
end Unit_2;

with Unit_1;
package Unit_3 is
end Unit_3;
$

Thanks for the pointers. I wonder if this is a bug or a feature?




^ permalink raw reply	[relevance 7%]

* Re: asynchronous task communication
  2013-01-05  5:18  6%                           ` Charles Hixson
  2013-01-05  8:48  0%                             ` Niklas Holsti
@ 2013-01-08  2:41  0%                             ` Randy Brukardt
  1 sibling, 0 replies; 200+ results
From: Randy Brukardt @ 2013-01-08  2:41 UTC (permalink / raw)


"Charles Hixson" <charleshixsn@earthlink.net> wrote in message 
news:E_6dnZMOnLGnJHrNnZ2dnUVZ_rednZ2d@earthlink.com...
...
> You are probably right that a good custom implementation would be more 
> efficient, but (as is probably obvious) I'm not very familiar with Ada. So 
> my presumption has been that the library implementation would not only be 
> much more likely to be correct than something that I wrote, but that it 
> would also be more efficient.

It definitely would be more correct, but it's unlikely to be more efficient. 
The issue being that the containers have to support fairly general 
facilities, while a custom implementation only needs to support what you 
actually need.

Typically, it makes sense to start by using the containers, but then 
planning to switch to a custom structure if they are not fast enough. (It's 
usually very hard to tell what *really* is going to be the bottleneck until 
you at least have a prototype implementation to test.)

But if you need access types, its pretty trivial to make a dynamic array 
type in Ada. Something like:

     type My_Vect is array (Positive range <>) of Some_Access_Type;
     type My_Vect_Access is access My_Vect;

Then, you just allocate the size needed with new:

     Obj := new My_Vect (1..10);

If you need to make the object bigger, just allocate a new one, copy the old 
one's elements into it, swap the access values, and deallocate the old one. 
Pretty simple.

> Well, the things that I'm planning on managing are themselves indefinite 
> in size, in that they contain variable length arrays,  So an access type 
> seems the right handle.  Besides, that allows me to call routines that 
> modify them without copying the whole thing.  But all I really want is a 
> variable size array.  The fancy stuff, like cursors, etc., don't seem to 
> have any application to my purpose.

Here is where you're confused. A cursor serves the same purpose for a 
container that an access type serves for one of the built-in datatypes. In 
addition, you get some (depends on the implementation exactly how much) 
dangling reference detection when you use cursors. (For some 
implementations, it's nearly complete.) And, when you use a container to 
store the objects, and cursors to provide the references to them, you don't 
have to worry about storage management at all. The container will manage it 
for you.

So I would probably put your objects into some container, and then use the 
cursors rather than access values in your Vectors. Then you can totally 
forget about storage management (unless and until you start running out of 
memory).

                                     Randy.




  I want an array, because I want to
> be able to directly address individual items.    OTOH, I don't even see 
> that I need to use tagged types, much less class wide variables.  So maybe 
> containers is the wrong thing to look at.  But it was the only variable 
> size array library that I found.
> Please note that when I say variable size, I'm not talking about 
> indefinite.  At each instant the array is definite in size...but the size 
> isn't a constant.  This kind of thing is normally implemented by an thing 
> that starts at some base size, and whenever it runs out of space it 
> allocates a new copy on the heap that will hold perhaps twice as many 
> items, and references to this new item replace the old item.  Which is the 
> kind of thing I thought Ada.Containers.Vectors was.  But details of the 
> implementation are important if you want this to be efficient, so I 
> thought I'd use the Ada.Containers library version.  It sounds like this 
> was a mistake.
>
>
> 





^ permalink raw reply	[relevance 0%]

* Re: asynchronous task communication
  2013-01-06 22:55  0%                               ` Charles Hixson
@ 2013-01-07  6:07  7%                                 ` Shark8
  0 siblings, 0 replies; 200+ results
From: Shark8 @ 2013-01-07  6:07 UTC (permalink / raw)


On Sunday, January 6, 2013 4:55:05 PM UTC-6, Charles Hixson wrote:
> On 01/05/2013 12:48 AM, Niklas Holsti wrote:
> 
> It has been suggested that my intended use of Vectors is a mistake.
> That it is unreasonable to store access variables into vectors. This is 
> a pity, as I know of no other Ada construct that would suit my needs.

I think that's some miscommunication, probably because prior to the Containers in Ada the only way to use "vectors" [read dynamically-sized arrays] for indefinite-types was (a) to use access values, or (b) construction via function. (This is really still the case, though (a) is cleaned up with implicit dereferencing.)

Your problem, as described, was that there could be multiple, varying-sized 'cells' which would be known at generation-time, but also might themselves need to grow. (A perfect candidate for Vector.)

You *could* store the access values (I'd recommend a not-null constraint, if possible) in an array, but unless you need to keep a big 'network' active (which sounds dubious with your mailbox/message analogy; though you might need it in a different part than the message-box).

With Indefinite_Vectors you could have something like the following:
Type Message( Length: Positive ) is record
  Data : Array(1..Length) of Character:= ( Others => ' ' );
end record;

Package Message_Box_Pkg is New Ada.Containers.Indefinite_Vector( Positive, Message );

Message_Box : Message_Box_Pkg.Vector;

And that's it.
Indeed, going with the "apartment wall of mailboxes" you could do something like:

Subtype Apt_Address is Positive;
Package Mail_Wall is Ada.Containers.Indefinite_Vector
  ( Apt_Address, Message_Box_Pkg.Vector );

Mail_Center : Mail_Wall.Vector;

As you can see, none of those are using (exposed) access types; which is generally a good thing.

For using vectors w/ access values, you could use something like this:

Type Cell(<>);
Type Link is Not Null Access Cell;
Type Data is Array(Positive Range <>) of Link;

Type Cell( References: Natural ) is
  case References is
    When 0 => Null;
    -- You might even be able to change Links to a Vector_Package.Vector
    When others => Links : Data(1..References);
  end case;
end record;

Package Vector_Package is new Ada.Containers.Vectors(Positive, Link);

Petri_Dish : Vector_Package.Vector;



^ permalink raw reply	[relevance 7%]

* Re: asynchronous task communication
  2013-01-05  8:48  0%                             ` Niklas Holsti
@ 2013-01-06 22:55  0%                               ` Charles Hixson
  2013-01-07  6:07  7%                                 ` Shark8
  0 siblings, 1 reply; 200+ results
From: Charles Hixson @ 2013-01-06 22:55 UTC (permalink / raw)


On 01/05/2013 12:48 AM, Niklas Holsti wrote:
> On 13-01-05 07:18 , Charles Hixson wrote:
>>> "Charles Hixson"<charleshixsn@earthlink.net>   wrote in message
>>> news:MY2dnX5O5NO_TXnNnZ2dnUVZ_hudnZ2d@earthlink.com...
>>> ....
>>>> And I'm sure there
>>>> must be some reasonable way to deallocate a Vector.
>    [ snip ]
>> Well, I've now been through the relevant section of the AARM, and
>> there's nothing about deallocating Vectors.  The contents of the vector,
>> yes, but not the vector itself.  Perhaps this means it's safe to use
>> Unchecked_Deallocation on the vector, as long as *I* don't have any
>> dangling pointers.
>
> It means that Vectors handle their own storage, more or less as if there
> is automatic garbage collection especially for the data in Vector
> objects. The implementation uses the Ada "Controlled" types to ensure
> that when a Vector object goes out of scope and disappears, the storage
> it has allocated to hold the data is automatically deallocated.
>
> You should not use Unchecked_Deallocation on a Vector, unless, of
> course, you yourself have explicitly allocated the Vector itself on the
> heap, with the "new" syntax. If you do allocate a Vector on the heap,
> and then do Unchecked_Deallocation on the (access to the) Vector, the
> storage that the Vector has allocated for its data is automatically
> deallocated as a consequence of finalizing the Vector object as part of
> the Unchecked_Deallocation.
>
> The end result is that, from the storage allocation point of view, you
> can think of a Vector in the same way as you think of an ordinary array
> (of a fixed size). When the program leaves the block in which the array
> variable was declared, the storage for the array is automatically
> discarded. The same holds for Vectors (and the other standard Ada
> containers).
>
> If your ordinary array holds accesses to other objecs, nothing happens
> to those other objects when the array is discarded (there is no
> automatic "deep" deallocation). The same holds for Vectors: if the
> Vector holds accesses to other objecs, only the accesses are discarded
> when the Vector is discarded; nothing happens to those other accessed
> objects.
>
>> But all I really want is a
>> variable size array. ....
>> This kind of thing is normally implemented by an
>> thing that starts at some base size, and whenever it runs out of space
>> it allocates a new copy on the heap that will hold perhaps twice as many
>> items, and references to this new item replace the old item.  Which is
>> the kind of thing I thought Ada.Containers.Vectors was.
>
> You were right (although the implementation is of course hidden).
>
>> But details of
>> the implementation are important if you want this to be efficient, so I
>> thought I'd use the Ada.Containers library version.  It sounds like this
>> was a mistake.
>
>  From the functional point of view, Ada.Containers is exactly what you
> want. From the performance point of view, note that the Ada standard
> containers come with some big-Oh complexity requirements. But the only
> way to find out if they are fast enough for you is to measure.
>
> If you don't need cursors, and are not worried about what may happen if
> some parts of your application insert or delete elements in a Vector
> that another part of your application is traversing in a loop, you could
> probably make a slightly faster implementation of variable-sized arrays.
> I have several such simple implementations, created before
> Ada.Containers existed. I don't know if they are faster than Ada
> Vectors, though, and I plan to retire them by and by, and switch to
> Ada.Containers.
>
It has been suggested that my intended use of Vectors is a mistake. 
That it is unreasonable to store access variables into vectors.  This is 
a pity, as I know of no other Ada construct that would suit my needs. 
(I *do* need to deallocate the vectors, though.  I understood that I 
would need to handle the deallocation of the items that the access 
variables referred to, but I need to be able to deallocate "objects" 
that contain the vectors.

Perhaps I should wait until there is a good text on using them.  I don't 
seem to use the correct language for people to understand what I'm 
talking about, even when I'm not being a bit fuzzy because I'm confused. 
  (And I must admit that this happens often when I am trying to 
understand some parts of Ada.  If it isn't described in Barnes, Ada 95, 
I'm likely to not know how to talk about it.)

At all events, the discussion on how to implement concurrency locking 
has been very valuable to me, and clarified many ideas that I had on the 
subject.  I appreciate this a lot.




^ permalink raw reply	[relevance 0%]

* Re: On Style: Any opinions on *not* capitalising the first letter of verbs in a procedure name ?
  2013-01-04 18:32  0% ` Simon Wright
@ 2013-01-05 14:11  0%   ` Stephen Leake
  0 siblings, 0 replies; 200+ results
From: Stephen Leake @ 2013-01-05 14:11 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> Rod Kay <rodakay@internode.on.net> writes:
>
>>    declare
>>       package Integer_Vectors is new Ada.Containers.Vectors (Positive, Integer);
>>       
>>       Integers : Integer_Vectors.Vector;
>>    begin
>>       Integers.reserve_Capacity;
>>       Integers.clear;
>>    end;
>>
>>
>> The idea is to only capitalise the noun parts of the procedure
>> name. It's a minor thing I guess, yet I find code a little easier to
>> read when used.
>
> I like my IDE (Emacs) to capitalise for me, and this would need so many
> case exceptions that it'd become impractical.

Unless you add a dictionary of verbs/nouns. Maybe automated lookup into
the on-line OED - do they have an API? A lot of work for very little
gain! But it would be cool if it worked :)

Which reminds me; we need a simpler keybinding for "make this word a
case exception".

-- 
-- Stephe



^ permalink raw reply	[relevance 0%]

* Re: On Style: Any opinions on *not* capitalising the first letter of verbs in a procedure name ?
  2013-01-04  4:27  5% On Style: Any opinions on *not* capitalising the first letter of verbs in a procedure name ? Rod Kay
  2013-01-04 16:31  0% ` Adam Beneschan
  2013-01-04 18:32  0% ` Simon Wright
@ 2013-01-05 14:06  0% ` Stephen Leake
  2 siblings, 0 replies; 200+ results
From: Stephen Leake @ 2013-01-05 14:06 UTC (permalink / raw)


Rod Kay <rodakay@internode.on.net> writes:

>    declare
>       package Integer_Vectors is new Ada.Containers.Vectors (Positive, Integer);
>       
>       Integers : Integer_Vectors.Vector;
>    begin
>       Integers.reserve_Capacity;
>       Integers.clear;
>    end;
>
>
>    The idea is to only capitalise the noun parts of the procedure
>    name. It's a minor thing I guess, yet I find code a little easier
>    to read when used.
>
>    So any thoughts ? ... good, bad or ugly ?

If you can teach Emacs and/or GPS to do this automatically, it might be
useful. (It would be a big job; you'd need a good dictionary or
something similar).

Otherwise, it's a non-starter; it's too small an issue to spend
time/brain power on.

-- 
-- Stephe



^ permalink raw reply	[relevance 0%]

* Re: asynchronous task communication
  2013-01-05  5:18  6%                           ` Charles Hixson
@ 2013-01-05  8:48  0%                             ` Niklas Holsti
  2013-01-06 22:55  0%                               ` Charles Hixson
  2013-01-08  2:41  0%                             ` Randy Brukardt
  1 sibling, 1 reply; 200+ results
From: Niklas Holsti @ 2013-01-05  8:48 UTC (permalink / raw)


On 13-01-05 07:18 , Charles Hixson wrote:
>> "Charles Hixson"<charleshixsn@earthlink.net>  wrote in message
>> news:MY2dnX5O5NO_TXnNnZ2dnUVZ_hudnZ2d@earthlink.com...
>> ....
>>> And I'm sure there
>>> must be some reasonable way to deallocate a Vector. 
  [ snip ]
> Well, I've now been through the relevant section of the AARM, and
> there's nothing about deallocating Vectors.  The contents of the vector,
> yes, but not the vector itself.  Perhaps this means it's safe to use
> Unchecked_Deallocation on the vector, as long as *I* don't have any
> dangling pointers.

It means that Vectors handle their own storage, more or less as if there
is automatic garbage collection especially for the data in Vector
objects. The implementation uses the Ada "Controlled" types to ensure
that when a Vector object goes out of scope and disappears, the storage
it has allocated to hold the data is automatically deallocated.

You should not use Unchecked_Deallocation on a Vector, unless, of
course, you yourself have explicitly allocated the Vector itself on the
heap, with the "new" syntax. If you do allocate a Vector on the heap,
and then do Unchecked_Deallocation on the (access to the) Vector, the
storage that the Vector has allocated for its data is automatically
deallocated as a consequence of finalizing the Vector object as part of
the Unchecked_Deallocation.

The end result is that, from the storage allocation point of view, you
can think of a Vector in the same way as you think of an ordinary array
(of a fixed size). When the program leaves the block in which the array
variable was declared, the storage for the array is automatically
discarded. The same holds for Vectors (and the other standard Ada
containers).

If your ordinary array holds accesses to other objecs, nothing happens
to those other objects when the array is discarded (there is no
automatic "deep" deallocation). The same holds for Vectors: if the
Vector holds accesses to other objecs, only the accesses are discarded
when the Vector is discarded; nothing happens to those other accessed
objects.

> But all I really want is a
> variable size array. ....
> This kind of thing is normally implemented by an
> thing that starts at some base size, and whenever it runs out of space
> it allocates a new copy on the heap that will hold perhaps twice as many
> items, and references to this new item replace the old item.  Which is
> the kind of thing I thought Ada.Containers.Vectors was.

You were right (although the implementation is of course hidden).

> But details of
> the implementation are important if you want this to be efficient, so I
> thought I'd use the Ada.Containers library version.  It sounds like this
> was a mistake.

From the functional point of view, Ada.Containers is exactly what you
want. From the performance point of view, note that the Ada standard
containers come with some big-Oh complexity requirements. But the only
way to find out if they are fast enough for you is to measure.

If you don't need cursors, and are not worried about what may happen if
some parts of your application insert or delete elements in a Vector
that another part of your application is traversing in a loop, you could
probably make a slightly faster implementation of variable-sized arrays.
I have several such simple implementations, created before
Ada.Containers existed. I don't know if they are faster than Ada
Vectors, though, and I plan to retire them by and by, and switch to
Ada.Containers.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .



^ permalink raw reply	[relevance 0%]

* Re: asynchronous task communication
  @ 2013-01-05  5:18  6%                           ` Charles Hixson
  2013-01-05  8:48  0%                             ` Niklas Holsti
  2013-01-08  2:41  0%                             ` Randy Brukardt
  0 siblings, 2 replies; 200+ results
From: Charles Hixson @ 2013-01-05  5:18 UTC (permalink / raw)


On 01/03/2013 02:27 PM, Randy Brukardt wrote:
> "Charles Hixson"<charleshixsn@earthlink.net>  wrote in message
> news:MY2dnX5O5NO_TXnNnZ2dnUVZ_hudnZ2d@earthlink.com...
> ....
>> Yes, it's doable, but I'd *really* rather avoid that.  And I'm sure there
>> must be some reasonable way to deallocate a Vector.  That I don't know
>> what it is doesn't convince me that it doesn't exist.  Perhaps Clear or
>> Delete would do it, but I haven't found this documented.  I'm guessing
>> that if I store access variables in a Vector, and then deallocate the item
>> the access variable holds (updating the access variable to null), that
>> will free most of the space, but deallocating the Vector itself is not so
>> clear.  I can't tell whether there are any handles to it that I don't know
>> about.  Perhaps it's somewhere in the AARM.
>
> I don't understand this comment (and probably no one else has, either, as no
> one has commented on it).
Well, I've now been through the relevant section of the AARM, and 
there's nothing about deallocating Vectors.  The contents of the vector, 
yes, but not the vector itself.  Perhaps this means it's safe to use 
Unchecked_Deallocation on the vector, as long as *I* don't have any 
dangling pointers.
>
> The entire reason the Ada.Containers library of packages (including Vectors)
> exists is to eliminate the need to manage storage. (If you don't mind
> managing the storage, the operations are trivial to write yourself, and
> probably more efficient as well.) As such, there is quite purposely no
> visibility into the storage management of any of the Ada.Containers. All
> that's required is that the memory is freed when the object is destroyed or
> overwritten (see A.18.2(253)).
>
> Of course, if you're putting an access to some object into a container, you
> still have to manage the storage for the object. It's better (but not always
> possible) to put the objects themselves directly into the containers. When
> that's not possible, sometimes its possible to put cursors (for another
> container) into a container. In both cases, the containers will manage the
> storage so you don't have to.
It would be possible to put the objects directly into the containers, I 
think.  But they will be changing a lot, and copying them in and out 
would be undesirable.  But my main reason for using the container is to 
get a variable size array.  (Second thoughts:  No, it wouldn't be 
possible to put the items into a container, if I substitute item for 
access variables, because there is a mutual reference and forward 
reference, and everything would end up as one big lump.)
>
> Personally, I wouldn't bother with using a Vector container for access
> values. You're still going to have to do most of the storage management
> yourself; you might as well do all of it yourself. An access to
> unconstrained array of access values is easy to manage and you won't have
> any questions about when memory is freed. The most painful case happens when
> you need to grow the structure, but just copying it into a larger value is
> not likely to be very expensive because of the small size of the
> elements.(After all, this is pretty much what is happening inside of an
> instance of Vectors.)
You are probably right that a good custom implementation would be more 
efficient, but (as is probably obvious) I'm not very familiar with Ada. 
  So my presumption has been that the library implementation would not 
only be much more likely to be correct than something that I wrote, but 
that it would also be more efficient.
>
> The big value of the containers is when managing large elements directly,
> especially indefinite elements like class-wide objects (something Ada
> doesn't allow you to do directly). Just because you *can* store access
> values into a container doesn't mean you should. But of course YMMV.
>
>                                            Randy.
Well, the things that I'm planning on managing are themselves indefinite 
in size, in that they contain variable length arrays,  So an access type 
seems the right handle.  Besides, that allows me to call routines that 
modify them without copying the whole thing.  But all I really want is a 
variable size array.  The fancy stuff, like cursors, etc., don't seem to 
have any application to my purpose.  I want an array, because I want to 
be able to directly address individual items.    OTOH, I don't even see 
that I need to use tagged types, much less class wide variables.  So 
maybe containers is the wrong thing to look at.  But it was the only 
variable size array library that I found.
Please note that when I say variable size, I'm not talking about 
indefinite.  At each instant the array is definite in size...but the 
size isn't a constant.  This kind of thing is normally implemented by an 
thing that starts at some base size, and whenever it runs out of space 
it allocates a new copy on the heap that will hold perhaps twice as many 
items, and references to this new item replace the old item.  Which is 
the kind of thing I thought Ada.Containers.Vectors was.  But details of 
the implementation are important if you want this to be efficient, so I 
thought I'd use the Ada.Containers library version.  It sounds like this 
was a mistake.






^ permalink raw reply	[relevance 6%]

* Re: On Style: Any opinions on *not* capitalising the first letter of verbs in a procedure name ?
  2013-01-04  4:27  5% On Style: Any opinions on *not* capitalising the first letter of verbs in a procedure name ? Rod Kay
  2013-01-04 16:31  0% ` Adam Beneschan
@ 2013-01-04 18:32  0% ` Simon Wright
  2013-01-05 14:11  0%   ` Stephen Leake
  2013-01-05 14:06  0% ` Stephen Leake
  2 siblings, 1 reply; 200+ results
From: Simon Wright @ 2013-01-04 18:32 UTC (permalink / raw)


Rod Kay <rodakay@internode.on.net> writes:

>    declare
>       package Integer_Vectors is new Ada.Containers.Vectors (Positive, Integer);
>       
>       Integers : Integer_Vectors.Vector;
>    begin
>       Integers.reserve_Capacity;
>       Integers.clear;
>    end;
>
>
> The idea is to only capitalise the noun parts of the procedure
> name. It's a minor thing I guess, yet I find code a little easier to
> read when used.

I like my IDE (Emacs) to capitalise for me, and this would need so many
case exceptions that it'd become impractical.



^ permalink raw reply	[relevance 0%]

* Re: On Style: Any opinions on *not* capitalising the first letter of verbs in a procedure name ?
  2013-01-04  4:27  5% On Style: Any opinions on *not* capitalising the first letter of verbs in a procedure name ? Rod Kay
@ 2013-01-04 16:31  0% ` Adam Beneschan
  2013-01-04 18:32  0% ` Simon Wright
  2013-01-05 14:06  0% ` Stephen Leake
  2 siblings, 0 replies; 200+ results
From: Adam Beneschan @ 2013-01-04 16:31 UTC (permalink / raw)


On Thursday, January 3, 2013 8:27:42 PM UTC-8, Rod Kay wrote:
> Hi folks,
> 
>    I've been trialling this style and come to like it. An example would be ...

>    declare
>       package Integer_Vectors is new Ada.Containers.Vectors (Positive, Integer);
> 
>       Integers : Integer_Vectors.Vector;
>    begin
>       Integers.reserve_Capacity;
>       Integers.clear;
>    end;
> 
>    The idea is to only capitalise the noun parts of the procedure name. It's a minor thing I guess, yet I find code a little easier to read when used.

That would make sense if German is your first language, I suppose.  To me, whose main language is (American) English, it just looks a little weird, aesthetically.  But I don't find it either easier or more difficult to read either way.

Just my 2 Pfennig,

                             -- Adam



^ permalink raw reply	[relevance 0%]

* On Style: Any opinions on *not* capitalising the first letter of verbs in a procedure name ?
@ 2013-01-04  4:27  5% Rod Kay
  2013-01-04 16:31  0% ` Adam Beneschan
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Rod Kay @ 2013-01-04  4:27 UTC (permalink / raw)


Hi folks,

   I've been trialling this style and come to like it. An example would be ...


   declare
      package Integer_Vectors is new Ada.Containers.Vectors (Positive, Integer);
      
      Integers : Integer_Vectors.Vector;
   begin
      Integers.reserve_Capacity;
      Integers.clear;
   end;


   The idea is to only capitalise the noun parts of the procedure name. It's a minor thing I guess, yet I find code a little easier to read when used.

   On the other hand, the half dozen Ada people I've discussed the style with have been dubious at best.

   So any thoughts ? ... good, bad or ugly ?


regards.



^ permalink raw reply	[relevance 5%]

* Re: IBM 437 encoded String to UTF-16 Wide_String
  @ 2012-11-28 17:35  6%                   ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2012-11-28 17:35 UTC (permalink / raw)


On 28.11.12 15:23, Dmitry A. Kazakov wrote:
> On Wed, 28 Nov 2012 14:47:10 +0100, Georg Bauhaus wrote:
> 
>> On 28.11.12 14:36, Dmitry A. Kazakov wrote:
>>> The problem is not construction of a container
>>> type. It is the relation of the obtained type to the string interface. The
>>> string interface is an array of code points. The container must implement
>>> this interface in order to be a string. All strings must implement this
>>> interface, this is why they are called "strings."
>>
>> This says that a string interface consists of operations
>> that allow us to use string objects like one uses arrays.
> 
> It say that instance implementing the interface are substitutable where a
> string is expected. You should be able to pass IBM_437_String to Put_Line,
> Trim, To_Lower etc.
> 
>> Is this set of array ops not included in a Vector's interface,
> 
> By which means the language or the reader knows if it is?

This is why I mentioned generics. It is not nice, but lets the
reader see the expected interface:

   generic
      type Apple is (<>);

      with package V is
        new Ada.Containers.Vectors (Element_Type => Apple,
                                    others => <>);
   package String_Ops is

      type String is new V.Vector with null record;

      Pattern_Error : exception;

      procedure Put_Line (Source : String);  -- not normally here

      function Slice (Source : String;
                      Low    : V.Index_Type;
                      High   : V.Extended_Index) return String;

      function Index (Source, Pattern : String) return V.Extended_Index;

   end String_Ops;

Or even

   generic
      type Element_Type is ...
   package Ada.Containers.Strings is ...

I don't prefer these types of generics to an improved type system,
one that is less complex and less full of historical reasons.
But since Ada is not going to get this sort of type system...

> Ada had manifesting type system, so far...
> 
>> Which algorithms require a String_Interface that excludes
>> other array/vector operations?
> 
> ?

That is, is there a set difference between string operations
and "vector" operations such that, from a user's perspective,
nothing could turn vectors into objects of type String, or
Wide_String, or Wide_Wide_String?




^ permalink raw reply	[relevance 6%]

* Re: Ada202X : Adding functors
  2012-11-15 12:31  7%     ` Georg Bauhaus
@ 2012-11-15 12:46  0%       ` Martin
  0 siblings, 0 replies; 200+ results
From: Martin @ 2012-11-15 12:46 UTC (permalink / raw)


On Thursday, November 15, 2012 12:31:42 PM UTC, Georg Bauhaus wrote:
> On 15.11.12 08:12, Martin wrote:
> 
> > Yup...I think I listed lambdas in another post...possibly even my 'No 1'! No chance of me using them in my C++ work, our compilers aren't up to C++11.
> 
> >
> 
> 
> 
> If lambda-expressions should help with not naming small
> 
> expressions that don't deserve a name (that'll be fun!),
> 
> and if lambda-expressions need not be passed upwards,
> 
> then maybe more along the lines of if-expressions, and
> 
> expression functions,
> 
> 
> 
> with Ada.Containers.Vectors;
> 
> 
> 
> procedure Foo is
> 
>     
> 
>     package Nats is new Ada.Containers.Vectors
> 
>       (Index_Type => Positive,
> 
>        Element_Type => Natural);
> 
> 
> 
>     V : Nats.Vector;
> 
>     Sum : Natural := 0;
> 
> 
> 
> begin  -- not Ada
> 
> 
> 
>     V.Iterate (Process => (with (Position : Cursor) do
> 
>                              Sum := Sum + Element (Position)));
> 
> 
> 
>     declare
> 
>        Copy2 : Nats.Vector;
> 
>     begin
> 
>        for E of V loop
> 
>           Copy2.Append
> 
>             (New_Item =>
> 
>                (with (X : Natural => E) return Natural is
> 
>                   2 * X));
> 
>        end loop;
> 
>     end;
> 
> 
> 
> end Foo;

+1



^ permalink raw reply	[relevance 0%]

* Re: Ada202X : Adding functors
  @ 2012-11-15 12:31  7%     ` Georg Bauhaus
  2012-11-15 12:46  0%       ` Martin
  0 siblings, 1 reply; 200+ results
From: Georg Bauhaus @ 2012-11-15 12:31 UTC (permalink / raw)


On 15.11.12 08:12, Martin wrote:
> Yup...I think I listed lambdas in another post...possibly even my 'No 1'! No chance of me using them in my C++ work, our compilers aren't up to C++11.
>

If lambda-expressions should help with not naming small
expressions that don't deserve a name (that'll be fun!),
and if lambda-expressions need not be passed upwards,
then maybe more along the lines of if-expressions, and
expression functions,

with Ada.Containers.Vectors;

procedure Foo is
    
    package Nats is new Ada.Containers.Vectors
      (Index_Type => Positive,
       Element_Type => Natural);

    V : Nats.Vector;
    Sum : Natural := 0;

begin  -- not Ada

    V.Iterate (Process => (with (Position : Cursor) do
                             Sum := Sum + Element (Position)));

    declare
       Copy2 : Nats.Vector;
    begin
       for E of V loop
          Copy2.Append
            (New_Item =>
               (with (X : Natural => E) return Natural is
                  2 * X));
       end loop;
    end;

end Foo;




^ permalink raw reply	[relevance 7%]

* Re: Copy vector in Ada
  2012-10-31 16:26  6% Copy vector in Ada katolsster
@ 2012-10-31 16:37  6% ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2012-10-31 16:37 UTC (permalink / raw)


On 10/31/2012 09:26 AM, katolsster wrote:
 >
 > I'm trying to figure out the best way to copy a vector into another vector
 > (Ada.Containers.Vectors). Is copying element by element the only way? My
 > vectors are tiny (in the order of max 5 elements).

What wrong with assignment (":=")?

-- 
Jeff Carter
"Mr. President, we must not allow a mine-shaft gap!"
Dr. Strangelove
33



^ permalink raw reply	[relevance 6%]

* Copy vector in Ada
@ 2012-10-31 16:26  6% katolsster
  2012-10-31 16:37  6% ` Jeffrey Carter
  0 siblings, 1 reply; 200+ results
From: katolsster @ 2012-10-31 16:26 UTC (permalink / raw)


Hello, 
I'm trying to figure out the best way to copy a vector into another vector (Ada.Containers.Vectors). Is copying element by element the only way? My vectors are tiny (in the order of max 5 elements). 





^ permalink raw reply	[relevance 6%]

* Re: API design considerations - variable-length array in record type
  2012-10-08  9:03  6% API design considerations - variable-length array in record type Maciej Sobczak
  2012-10-08 11:13  0% ` Simon Wright
  2012-10-08 11:29  0% ` Egil Høvik
@ 2012-10-09  3:10  0% ` Stephen Leake
  2 siblings, 0 replies; 200+ results
From: Stephen Leake @ 2012-10-09  3:10 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

> Hi,
>
> I am working on the API design where there is a need for a record type
> with field(s) that are arrays of some predefined type (say, Integer).
> So, an example record type might look like this:
>
> type R is record
>    X : Integer;
>    Y : Unbounded_String;
>    Z : Array_Of_Integers_That_We_Talk_About_Here;
> end record;
>
> A straightforward choice is a predefined instantiation of
> Ada.Containers.Vectors for Integer and this would be probably the
> least surprising, especially in the context of Y : Unbounded_String,
> but at the same time I'm open to consider some more lightweight
> alternatives.
> The problem is - any other alternative I can think of leads to the
> complication of API in the form of introducing
> Ada.Finalization.Controlled to the picture.
>
> Do you have some favourite solutions?

Ada.Containers.Bounded_Vectors meets these requirements.

-- 
-- Stephe



^ permalink raw reply	[relevance 0%]

* Re: API design considerations - variable-length array in record type
  2012-10-08  9:03  6% API design considerations - variable-length array in record type Maciej Sobczak
  2012-10-08 11:13  0% ` Simon Wright
@ 2012-10-08 11:29  0% ` Egil Høvik
  2012-10-09  3:10  0% ` Stephen Leake
  2 siblings, 0 replies; 200+ results
From: Egil Høvik @ 2012-10-08 11:29 UTC (permalink / raw)


On Monday, October 8, 2012 11:03:04 AM UTC+2, Maciej Sobczak wrote:
> 
> A straightforward choice is a predefined instantiation of Ada.Containers.Vectors for Integer and this would be probably the least surprising, especially in the context of Y : Unbounded_String, but at the same time I'm open to consider some more lightweight alternatives.
> 

If you don't mind using Ada 2012 packages, there's also Ada.Containers.Indefinite_Holders (RM A.18.18).
I haven't used it myself yet, so I can't say anything about how lightweight it is compared to Vector.

-- 
~egilhh



^ permalink raw reply	[relevance 0%]

* Re: API design considerations - variable-length array in record type
  2012-10-08  9:03  6% API design considerations - variable-length array in record type Maciej Sobczak
@ 2012-10-08 11:13  0% ` Simon Wright
  2012-10-08 11:29  0% ` Egil Høvik
  2012-10-09  3:10  0% ` Stephen Leake
  2 siblings, 0 replies; 200+ results
From: Simon Wright @ 2012-10-08 11:13 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

> A straightforward choice is a predefined instantiation of
> Ada.Containers.Vectors for Integer and this would be probably the
> least surprising, especially in the context of Y : Unbounded_String,
> but at the same time I'm open to consider some more lightweight
> alternatives.

This would be my choice!

> The problem is - any other alternative I can think of leads to the
> complication of API in the form of introducing
> Ada.Finalization.Controlled to the picture.

You could use "private with".



^ permalink raw reply	[relevance 0%]

* API design considerations - variable-length array in record type
@ 2012-10-08  9:03  6% Maciej Sobczak
  2012-10-08 11:13  0% ` Simon Wright
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Maciej Sobczak @ 2012-10-08  9:03 UTC (permalink / raw)


Hi,

I am working on the API design where there is a need for a record type with field(s) that are arrays of some predefined type (say, Integer). So, an example record type might look like this:

type R is record
   X : Integer;
   Y : Unbounded_String;
   Z : Array_Of_Integers_That_We_Talk_About_Here;
end record;

The trouble is, the types involved should comply with the following requirements:

- the enclosing record type should not be limited (it should be copyable)
- the record type can be explicitly controlled, if necessary
- the record type should be definite (it should not require initialization)
- it should be possible to assign to Z, just as it is possible to assign to X and Y, and the new value for Z *might have a different length*

An important relaxation is that it is not necessary to support in-place modifications of the field in question. That is, Y above can be modified (by appending or modifying individual characters, for example) in place. It is not necessary to support it for Z, assignment of the whole array is the only operation that is needed there.

A straightforward choice is a predefined instantiation of Ada.Containers.Vectors for Integer and this would be probably the least surprising, especially in the context of Y : Unbounded_String, but at the same time I'm open to consider some more lightweight alternatives.
The problem is - any other alternative I can think of leads to the complication of API in the form of introducing Ada.Finalization.Controlled to the picture.

Do you have some favourite solutions?

For comparison, in C++ this would be solved with std::vector<int>, which suggests Ada.Containers.Vectors for Ada; but in Java this would be done simply with int[], which is conceptually lighter and easier to use in this particular context.

-- 
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[relevance 6%]

* begin/end reducing memory consumption?
@ 2012-06-22  9:08  3% Anonymous
  0 siblings, 0 replies; 200+ results
From: Anonymous @ 2012-06-22  9:08 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3190 bytes --]

Hi all,

I'm currently evaluating Ada as an alternative to C++ for scientific programming. I have a simple test program that within its main loop repeatedly calls the following procedure:

procedure Propagate is
   Access_Temp : constant Access_Probability_Field
     := Access_New_Field;
begin
   Access_New_Field.all := (others => (others => (others => 0.0)));
   
   for Nx in -Fringe_Index .. Fringe_Index loop
   -- Fringe_Index = about 50
      for Ny in -Fringe_Index .. Fringe_Index loop
         for Ntheta in Angle_Index'Range loop
         -- Range = 0 .. 199
            begin -- why do I need this?
               for W of Weight_Vectors (Ntheta) loop
-- Weight_Vectors (Ntheta) is a Vector of type Ada.Containers.Vectors
-- (Element_Type => Weight, Index_Type => Natural), where Weight is defined as
-- subtype Pixel_Offset is Integer range -Max_Offset .. Max_Offset;
-- type Weight is record
--   Nx, Ny : Pixel_Offset;
--   W : Long_Float;
-- end record;
                  for D_Index in Angular_Propagator'Range loop
                     Access_New_Field
                       (Nx + W.Nx, Ny + W.Ny, Ntheta + D_Index)
                       := Access_New_Field --  (Nx, Ny + 1, Ntheta)
                       (Nx + W.Nx, Ny + W.Ny, Ntheta + D_Index)
                       + Access_Old_Field (Nx, Ny, Ntheta) * W.W
                       * Angular_Propagator (D_Index);
                  end loop;
               end loop;
            end;
         end loop;
      end loop;
   end loop;
   Access_New_Field := Access_Old_Field;
   Access_Old_Field := Access_Temp;
end Propagate;

Access_New_Field and Access_Old_Field are of type access Probability_Field, where

   type Probability_Field is array
     (Pixel_Index'Range, Pixel_Index'Range, Angle_Index'Range)
     of Long_Float;

   subtype Pixel_Index is Integer range
     -(Fringe_Index + Max_Offset) .. (Fringe_Index + Max_Offset);

my main loop looks like this:

      Access_New_Field := new Probability_Field;
      Access_Old_Field := new Probability_Field;

      for K in 1 .. No_Iterations loop
         Put_Line ("Iteration " & Integer'Image (K));
         Propagate;
      end loop;

What I don't get is that if I comment out the above "begin/end" lines,
then memory usage increases with No_iterations and for No_iterations = 8 
reaches about 550 MB. Including begin/end reduces memory usage to 37MB (then independent of No_iterations, as it should be). For what it's worth, I'm using the following compiler flags (with GNAT GPL 2011 on Mac OS X 10.7.4, 2010 MacBook Pro):

gnatmake -o Main Main -P"/Users/sebastian/Documents/Studium/Research/hard-disk-disorder/lattice-propagator/release.gpr" -g -cargs -gnatq -gnatQ -bargs  -largs 


gcc -c -gnatQ -O3 -gnatp -gnat2012 -g -gnatq -gnatQ -I- -gnatA [�]/Main.adb
gcc -c -gnatQ -O3 -gnatp -gnat2012 -g -gnatq -gnatQ -I- -gnatA [�]/lattice_propagator.adb
gcc -c -gnatQ -O3 -gnatp -gnat2012 -g -gnatq -gnatQ -I- -gnatA [�]/geometry.adb
gnatbind -E -static -I- -x [�]/obj/main.ali
gnatlink [�]/obj/main.ali -g -o [�]/build/Main

Is this expected behaviour? If yes, could someone please explain what's going on internally?
Best regards,
Sebastian




^ permalink raw reply	[relevance 3%]

* Re: Distributed Systems Annex, data sharing between programs
  @ 2012-06-08  6:31  5%                 ` Pascal Obry
  0 siblings, 0 replies; 200+ results
From: Pascal Obry @ 2012-06-08  6:31 UTC (permalink / raw)



Shark8,

> Could you give examples of what sorts of tasks are better-suited/easier in DSA and YAMI4?

with Ada.Containers.Vectors;
package Flt_Vector is new (Positive, Float);
pragma Remote_Types (Flt_Vector);

with Flt_Vector; use Flt_Vector;

package A is
   pragma Remote_Call_Interface;

   procedure Call (V : in Flt_Vector);
end A;


Then using this from another partition across the network:

with A;
with Flt_Vector;

procedure Main is
   V : Flt_Vector.Vector;
begin
   V.Append (1.0);
   V.Append (4.5);
   A.Call (V);
end Main;

That is the vector is passed across the network and this just looks like
a procedure call in Ada. This is possible because the distributed
support is directly in Ada. With "foreign" distributed support (MPI for
example) you'll only get support for basic types. And of course, what is
done with Ada.Containers.Vectors is not magic, you can define your own
type and have serialization by specifying the 'Write and 'Read attribute
for the type.

Another very good point with the DSA is that the application can be
partitioned differently. With the same code base, just provides multiple
partitioning (different xyz.cfg passed to po_gnatdist). Where the
partition communication are hard coded into MPI you can in minute create
a new way to partition your DSA application and rebuild everything
without changing a line of code.

And if the code actually is on the same partition there is nothing
serialized, the call is direct as for non distributed application. This
gives the best performance in any partitioning.

Frankly I have used the DSA (I have also used MPI and RMI) and the Ada
solution is way better than any alternative I have used.

Note finally that AdaCore DSA support is done via PolyORB. This means
that you can communicate with your DSA application with CORBA or SOAP
for example. So you are not stuck on a proprietary protocol if you need
to open your application to other languages.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|    http://www.obry.net  -  http://v2p.fr.eu.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver keys.gnupg.net --recv-key F949BD3B




^ permalink raw reply	[relevance 5%]

* Re: Vector (container) initialization: the schizophrenic ampersand
  @ 2012-05-21 17:57  5%               ` Adam Beneschan
  0 siblings, 0 replies; 200+ results
From: Adam Beneschan @ 2012-05-21 17:57 UTC (permalink / raw)


On Monday, May 21, 2012 10:04:30 AM UTC-7, Robert A Duff wrote:
> Adam Beneschan writes:
> 
> > On Saturday, May 19, 2012 9:15:44 AM UTC-7, Robert A Duff wrote:
> >
> >> You don't need to qualify everything.  Just enough to disambiguate.
> >> I don't know what operators are visible in this example,
> >> nor what the context is, but this should work:
> >> 
> >>     T'(Element1 & Element2 & Element3)
> >
> > Sorry, it won't work.
> 
> Hmm.  You're probably right.  I'm not sure, because I haven't
> seen what "&" operators we're talking about, nor what
> the context is (is the concatenation assigned into
> a variable, passed to an overloaded procedure, ...?).

"T" is the Vector type from an instance of Ada.Containers.Vectors.  The & operators are also from the instance and have been made directly visible with "use".  The & operators can take all four combinations of Element&Element, Element&Vector, Vector&Element, Vector&Vector.  

                        -- Adam




^ permalink raw reply	[relevance 5%]

* Re: Problem in "X (1).Re := X (1).Re + 1"
  2012-05-09  8:41  6%             ` ytomino
@ 2012-05-10  0:52  0%               ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2012-05-10  0:52 UTC (permalink / raw)


"ytomino" <aghia05@gmail.com> wrote in message 
news:8861140.211.1336552896666.JavaMail.geo-discussion-forums@pbcrz9...
> On Wednesday, May 9, 2012 7:29:14 AM UTC+9, Randy Brukardt wrote:
>>
>> (Note that a copy-on-write implementation is not a good idea for the
>> standard containers for other reasons as well,
>
>> the main one being that the usual uses don't create many copies,
>
> Really?
> Ada.Containers.Vectors have some "&" operators.
> Many copies may be created when doing X & A & B & C...

Sure, the containers have some operations where this implementation would be 
a benefit. But I would guess that those operations would be used very rarely 
(if ever), so optimizing for them would be a mistake.

I think this is similar to the usage of the operations in 
Ada.Strings.Unbounded. There are many operations defined in that package, 
but most code I've seen only uses a handful of those operations. Optimizing 
for the other operations is wasted effort.

That's way I said it might make sense to use this implementation in your own 
container package, because your usage patterns might be far from typical. 
(There cannot be a one-size-really-fits-all implementation.)

                                  Randy. 





^ permalink raw reply	[relevance 0%]

* Re: Problem in "X (1).Re := X (1).Re + 1"
  @ 2012-05-09  8:41  6%             ` ytomino
  2012-05-10  0:52  0%               ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: ytomino @ 2012-05-09  8:41 UTC (permalink / raw)


On Wednesday, May 9, 2012 7:29:14 AM UTC+9, Randy Brukardt wrote:
> 
> (Note that a copy-on-write implementation is not a good idea for the 
> standard containers for other reasons as well,

> the main one being that the usual uses don't create many copies,

Really?
Ada.Containers.Vectors have some "&" operators.
Many copies may be created when doing X & A & B & C...

Of course, it's ineffective only at reference-counting because appending is one of writing.
More trick is required to use remained area in the capacity.
However, this optimization is possible.
For example, plural containers that are different length are able to share same data area if the areas filled by each container are same.

> so having overhead for that can't be 
> justified. But it should be possible to create a container with that 
> semantics.)



^ permalink raw reply	[relevance 6%]

* Re: Problem in "X (1).Re := X (1).Re + 1"
  2012-05-07 18:53  5%   ` ytomino
@ 2012-05-07 21:28  0%     ` Adam Beneschan
    0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2012-05-07 21:28 UTC (permalink / raw)


On Monday, May 7, 2012 11:53:58 AM UTC-7, ytomino wrote:
> On Tuesday, May 8, 2012 12:37:44 AM UTC+9, Adam Beneschan wrote:
> > 
> > No.  But if you change the 1 to 1.0 then I think it will be OK.
> 
> Oops!
> 1.0 is correct.
> 
> > I'm not yet really familiar with the ins and outs of user-defined references
> > and user-defined indexing.  But my guess is that the phrase in A.18.2(147.17)
> > that says "Reference returns an object whose discriminant is an access value
> > that designates the element designated by Position" means that Reference
> > can't return an object whose discriminant designates a *copy* of the element.
> > If I understand your question correctly, this means that the scenario you're
> > concerned about can't happen.
> 
> Imagine an implementation of an reference-counted container.
> Probably, it's like below:
> 
> function Reference (Container : Vector; Position : Cursor) return Ref_Type is
> begin
>    --  if data is shared, do copy-on-write to prepare for change
>    --  (memory management and exclusive control is omitted in this pseudo-code)
>    if Container.Data_Block.Ref_Count > 1 then
>       Container.Data_Block.Ref_Count := Container.Data_Block.Ref_Count - 1;
>       Container.Data_Block := new Data_Block_Type'(
>          Length => Container.Data_Block.Length,
>          Elements => (1 .. Length => Container.Data_Block.Elements (1 .. Length)),
>          Ref_Count => 1);
>    end if;
>    -- return access value designated by Position
>    return (Element => Container.Data_Block.Elements (To_Index (Cursor))'Access);
> end Reference;
> 
> And, similar copy-on-write is inserted into Replace_Element and Update_Element.
> 
> In this container, Reference copies its elements as your saying. But the container comes to own copied elements, and Reference returns an access value that designates the element in same area. I hope that this is allowed for effective implementations.
> Besides, if this is disallowed in Ada.Containers.Vectors, please assume my original container.
> Surely you don't think that all reference-counted containers written by user are forbidden to implement user-defined indexing.

OK, I think I figured out what you were talking about.  Sorry, but your original post seemed to use a few words (like "implemented by reference-counting") and expect that readers would fill in the rest of the details.  Unfortunately, I'm not a mind-reader, so it took me a lot of effort to figure it out.  Maybe others here are better mind-readers than I am.  I don't know.

But I'm guessing that you're referring to an implementation where, when a copy of an element is made, the implementation doesn't make a copy immediately, but rather waits until somebody tries to modify either the original or the copy and *then* splits off a copy.  So in your example:

  X(1).Re := X(1).Re + 1.0;

you're assuming that X(1) was earlier created as a copy of something else--or that something else was created as a copy of X(1).  The main ways I can see that this could be done are by using the Copy or Assign operations of vectors, e.g.

  X := Copy(W);
  X(1).Re := X(1).Re + 1.0;

so that when X is created, it's done by creating references to all the elements in W rather than by copying the elements of W; and then making a new copy of an individual element when it needs to be modified.  Of course, it's silly to do this if the element type is Complex, since it's surely easier to copy two floats than to implement all the overhead needed to deal with references.  But I can imagine that it might make sense if the element type is ... um, more complex than Complex.  Or a whole lot bigger.

I'm still dubious that it can work, though.  Consider:

  X := V.Copy(W);                        -- (A)
  Ref1 := V.Constant_Reference (W, 1);   -- (B)
  Ref2 := V.Constant_Reference (X, 1);   -- (C)
  X(1).Re := X(1).Re + 1.0;              -- (D)

If the Copy function did not create any new copies of elements, then Ref1.Element and Ref2.Element will end up being accesses to the same element, after (C) is performed.  If the new copy of the element is not created until Reference is evaluated by the left side of statement (D), the result is that either Ref2.Element (or possibly Ref1.Element) will be pointing at the wrong thing.  

So it looks to me like the method you suggest shouldn't be allowed, even in your own container, since it would make it impossible to implement Constant_Reference  correctly.

My caveat still applies, though; this involves issues that I'm not yet completely familiar with, so it's possible that I made a serious error.  I'm hoping someone will come to my rescue if I did ... :)

                        -- Adam




^ permalink raw reply	[relevance 0%]

* Re: Problem in "X (1).Re := X (1).Re + 1"
  2012-05-07 15:37  0% ` Adam Beneschan
@ 2012-05-07 18:53  5%   ` ytomino
  2012-05-07 21:28  0%     ` Adam Beneschan
  0 siblings, 1 reply; 200+ results
From: ytomino @ 2012-05-07 18:53 UTC (permalink / raw)


On Tuesday, May 8, 2012 12:37:44 AM UTC+9, Adam Beneschan wrote:
> 
> No.  But if you change the 1 to 1.0 then I think it will be OK.

Oops!
1.0 is correct.

> I'm not yet really familiar with the ins and outs of user-defined references
> and user-defined indexing.  But my guess is that the phrase in A.18.2(147.17)
> that says "Reference returns an object whose discriminant is an access value
> that designates the element designated by Position" means that Reference
> can't return an object whose discriminant designates a *copy* of the element.
> If I understand your question correctly, this means that the scenario you're
> concerned about can't happen.

Imagine an implementation of an reference-counted container.
Probably, it's like below:

function Reference (Container : Vector; Position : Cursor) return Ref_Type is
begin
   --  if data is shared, do copy-on-write to prepare for change
   --  (memory management and exclusive control is omitted in this pseudo-code)
   if Container.Data_Block.Ref_Count > 1 then
      Container.Data_Block.Ref_Count := Container.Data_Block.Ref_Count - 1;
      Container.Data_Block := new Data_Block_Type'(
         Length => Container.Data_Block.Length,
         Elements => (1 .. Length => Container.Data_Block.Elements (1 .. Length)),
         Ref_Count => 1);
   end if;
   -- return access value designated by Position
   return (Element => Container.Data_Block.Elements (To_Index (Cursor))'Access);
end Reference;

And, similar copy-on-write is inserted into Replace_Element and Update_Element.

In this container, Reference copies its elements as your saying. But the container comes to own copied elements, and Reference returns an access value that designates the element in same area. I hope that this is allowed for effective implementations.
Besides, if this is disallowed in Ada.Containers.Vectors, please assume my original container.
Surely you don't think that all reference-counted containers written by user are forbidden to implement user-defined indexing.



^ permalink raw reply	[relevance 5%]

* Re: Problem in "X (1).Re := X (1).Re + 1"
  2012-05-05 12:55  6% Problem in "X (1).Re := X (1).Re + 1" ytomino
@ 2012-05-07 15:37  0% ` Adam Beneschan
  2012-05-07 18:53  5%   ` ytomino
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2012-05-07 15:37 UTC (permalink / raw)


On Saturday, May 5, 2012 5:55:39 AM UTC-7, ytomino wrote:
> This is a thought experiment.
> 
> First, in RM 4.1.6:
> 
> * when the generalized_indexing is used within a primary where a name denoting a constant is permitted.
> 
> This means
> 
> declare
>    package V is new Vectors (Complex);
>    X : V.Vector;
> begin
>    X (1).Re := X (1).Re + 1;
> end;
> 
> is interpreted as
> 
> declare
>    package V is new Vectors (Complex);
>    X : V.Vector;
> begin
>    Reference (X, 1).Element.all.Re := Constant_Reference (X, 1).Element.all.Re + 1;
> end;
> 
> Is this OK?

No.  But if you change the 1 to 1.0 then I think it will be OK.

> 
> If this is the truth, and if Vectors is implemented by reference-counting.
> (I don't know copy-on-write is permitted in Ada.Containers.Vectors. Otherwise, please assume my original container like Vectors.)
> 
> Well then...
> May a next eval-order problem be caused or not?
> 
> 1. eval "Constant_Reference (X, 1)" => get an accessor pointing to shared data. (reference counter > 1)
> 2. eval "Reference (X, 1)" => do copy-on-write, and get an accessor pointing to new unshared data.
> 3. eval ".Element.all.Re" in right side => access *old* shared data. <- !!!!
> 4. eval ".Element.all.Re" in left side => access new data.
> 5. eval + 1 => calculate old data + 1.
> 6. eval assignment => store the result into new data.

I'm not yet really familiar with the ins and outs of user-defined references and user-defined indexing.  But my guess is that the phrase in A.18.2(147.17) that says "Reference returns an object whose discriminant is an access value that designates the element designated by Position" means that Reference can't return an object whose discriminant designates a *copy* of the element.  If I understand your question correctly, this means that the scenario you're concerned about can't happen.

But, as I said, I'm not completely familiar with all the issues involved.

                       -- Adam



^ permalink raw reply	[relevance 0%]

* Problem in "X (1).Re := X (1).Re + 1"
@ 2012-05-05 12:55  6% ytomino
  2012-05-07 15:37  0% ` Adam Beneschan
  0 siblings, 1 reply; 200+ results
From: ytomino @ 2012-05-05 12:55 UTC (permalink / raw)


This is a thought experiment.

First, in RM 4.1.6:

* when the generalized_indexing is used within a primary where a name denoting a constant is permitted.

This means

declare
   package V is new Vectors (Complex);
   X : V.Vector;
begin
   X (1).Re := X (1).Re + 1;
end;

is interpreted as

declare
   package V is new Vectors (Complex);
   X : V.Vector;
begin
   Reference (X, 1).Element.all.Re := Constant_Reference (X, 1).Element.all.Re + 1;
end;

Is this OK?

If this is the truth, and if Vectors is implemented by reference-counting.
(I don't know copy-on-write is permitted in Ada.Containers.Vectors. Otherwise, please assume my original container like Vectors.)

Well then...
May a next eval-order problem be caused or not?

1. eval "Constant_Reference (X, 1)" => get an accessor pointing to shared data. (reference counter > 1)
2. eval "Reference (X, 1)" => do copy-on-write, and get an accessor pointing to new unshared data.
3. eval ".Element.all.Re" in right side => access *old* shared data. <- !!!!
4. eval ".Element.all.Re" in left side => access new data.
5. eval + 1 => calculate old data + 1.
6. eval assignment => store the result into new data.

(Real compiler usually does not generate the strange order such as this. But "arbitrary order" is spelled out in RM 5.2.)

Of course, the result is same if shared data is alive.
However, on the worst case, the other task can deallocate shared data during from 1 to 3. Or, if the element type is controlled type or havs access value.

What do you think?

Thanks.



^ permalink raw reply	[relevance 6%]

* Re: Efficiency and overhead: Ada.Containers.Vectors.vector versus array type
  2012-01-21 19:11  5% ` Jeffrey Carter
@ 2012-01-22 15:05  7%   ` Ada BRL
  0 siblings, 0 replies; 200+ results
From: Ada BRL @ 2012-01-22 15:05 UTC (permalink / raw)


Thank you all for the interesting and useful suggestions!!!

I think I'll use the bounded arrays instead of vectors because, as you
said, this data structure fits more my purposes.



^ permalink raw reply	[relevance 7%]

* Re: Efficiency and overhead: Ada.Containers.Vectors.vector versus array type
  2012-01-21 18:19 13% Efficiency and overhead: Ada.Containers.Vectors.vector versus array type Ada BRL
  2012-01-21 18:40  6% ` Simon Wright
@ 2012-01-21 19:11  5% ` Jeffrey Carter
  2012-01-22 15:05  7%   ` Ada BRL
  1 sibling, 1 reply; 200+ results
From: Jeffrey Carter @ 2012-01-21 19:11 UTC (permalink / raw)


On 01/21/2012 11:19 AM, Ada BRL wrote:
>
> I need a "collection" of objects (every object has a lot of records
> like task objects, Gnat.Sockets and so on...);
> This collection is accessed several times during the execution.
> In the meantime I don't have to insert and delete any items during the
> execution, I just need to instantiate N object when the application
> starts and then the number of objects will remain the same throughout
> the execution.

This sounds perfect for an array. What is called a "vector" in the standard 
container library is an unbounded array. One uses an unbounded data structure 
when one doesn't know how large the structure will be until run time in such a 
way that one cannot declare a bounded structure; one uses a bounded structure 
(an array, in this case) in most other cases.

There's an additional reason you probably want an array rather than a vector: 
since your objects contain tasks, they are limited. You can't store limited 
objects in a vector, so you'll have to allocate them on the heap and store 
accesses to them in the vector. This introduces additional complexity to your 
code that would not appear when using an array. Also, since a vector is 
unbounded, it is also stored on the heap and accessed through an access value, 
making a vector involve double indirection.

Usually the syntax for dealing with an array is clearer than the equivalent 
using a vector (in current Ada; the next version of the standard will include 
changes to make them more equivalent).

-- 
Jeff Carter
"Run away! Run away!"
Monty Python and the Holy Grail
58

--- Posted via news://freenews.netfront.net/ - Complaints to news@netfront.net ---



^ permalink raw reply	[relevance 5%]

* Re: Efficiency and overhead: Ada.Containers.Vectors.vector versus array type
  2012-01-21 18:19 13% Efficiency and overhead: Ada.Containers.Vectors.vector versus array type Ada BRL
@ 2012-01-21 18:40  6% ` Simon Wright
  2012-01-21 19:11  5% ` Jeffrey Carter
  1 sibling, 0 replies; 200+ results
From: Simon Wright @ 2012-01-21 18:40 UTC (permalink / raw)


Ada BRL <ada.brl.2011@gmail.com> writes:

> I need some hints about Ada.Containers.Vectors.vector efficiency.
>
> I'm developing a multithreaded real time application in Ada.
>
> I need a "collection" of objects (every object has a lot of records
> like task objects, Gnat.Sockets and so on...);
> This collection is accessed several times during the execution.  In
> the meantime I don't have to insert and delete any items during the
> execution, I just need to instantiate N object when the application
> starts and then the number of objects will remain the same throughout
> the execution.
>
> Since I know how many object will be inside the collection I thought
> to use, as the collection I need, the "array standard type".  In the
> meanwhile the Ada.Containers.Vectors.vector object is far more
> practical, simple and has even more interesting and useful functions
> like iterators and so on.
>
> For this reason, since I don't have any experience in Ada, I ask you
> all what can you suggest me to use.
> If there is no such difference in efficiency/overhead between array
> types and Ada.Containers.Vectors.vector I'll definitely use the
> latter.

It's bound to take longer to, for example, iterate over a Vector than to
loop over an array. The question is, how much longer? and is that
acceptable for your proposed usage?

I'd have thought the actual operations you want to do on your objects
would be independent of the storage mechanism, so maybe you could use
the Vectors first, do some measurements, and see if that will be
adequate.

I'd  start by something like creating an Indefinite_Vector of Strings,
populating it with say 1000 strings, and seeing how long it takes to
iterate over it. I'd expect it to be sub-microsecond per element, on a
modern processor (but I could be wrong!)

One thing to be wary of: an object with an embedded task will be
limited, which means you can't hold it directly in any of the standard
Containers; you'd have to hold access-to-object (or
access-to-object'Class if you have tagged types). This means you'll need
to do storage management yourself, perhaps using Ada.Finalization.



^ permalink raw reply	[relevance 6%]

* Efficiency and overhead: Ada.Containers.Vectors.vector versus array type
@ 2012-01-21 18:19 13% Ada BRL
  2012-01-21 18:40  6% ` Simon Wright
  2012-01-21 19:11  5% ` Jeffrey Carter
  0 siblings, 2 replies; 200+ results
From: Ada BRL @ 2012-01-21 18:19 UTC (permalink / raw)


Hello everyone!

I need some hints about Ada.Containers.Vectors.vector efficiency.

I'm developing a multithreaded real time application in Ada.

I need a "collection" of objects (every object has a lot of records
like task objects, Gnat.Sockets and so on...);
This collection is accessed several times during the execution.
In the meantime I don't have to insert and delete any items during the
execution, I just need to instantiate N object when the application
starts and then the number of objects will remain the same throughout
the execution.

Since I know how many object will be inside the collection I thought
to use, as the collection I need, the "array standard type".
In the meanwhile the Ada.Containers.Vectors.vector object is far more
practical, simple and has even more interesting and useful functions
like iterators and so on.

For this reason, since I don't have any experience in Ada, I ask you
all what can you suggest me to use.
If there is no such difference in efficiency/overhead between array
types and Ada.Containers.Vectors.vector I'll definitely use the
latter.

Thank you so much!



^ permalink raw reply	[relevance 13%]

* Re: String_Holder ?
  @ 2011-12-19 11:12  7% ` Martin
  0 siblings, 0 replies; 200+ results
From: Martin @ 2011-12-19 11:12 UTC (permalink / raw)


On Dec 18, 12:34 pm, Natasha Kerensikova <lithium...@gmail.com> wrote:
> Hello,
>
> in my few Ada projects so far, I have quite often encountered the need
> of storing a string along with other information in records. So I went
> for discriminants containing the string size, and putting the string
> directly in the record.
>
> This works well when there is only one or two strings, but with several
> of them, or in variant records, I find it quite heavy. So I was thinking
> about something like that:
>
> type String_Holder is still to be defined;
>
> function Hold (S : String) return String_Holder;
>
> function To_String (Holder : String_Holder) return String;
>
> procedure Query (Holder : String_Holder;
>                  Process : not null access procedure (S : String));
>
> I'm still unsure on what kind of type String_Holder should be (private,
> tagged private or interface). It would basically be a constant-size
> reference to an immutable string that is stored "somewhere".
>
> The simplest implementation would be an Unbounded_String, though if
> needed it could be improved reference counting to make assignments
> cheaper, or with a hash table to deduplicate identical strings, etc.
>
> So my question is, does it make sense to have such objects? Or am I
> getting blinded by my C past, where strings are always manipulated
> through a char* object?
>
> Assuming it does make sense, am I right in thinking it's better to have
> such a type, even if it's a thin wrapper around Unbounded_String,
> instead of using directly Unbounded_String?
>
> Assuming it does make sense to have a String_Holder, would it be better
> to have it private, tagged private or interface?
> My guess is that tagged private has no advantage over interface,
> especially with a default implementation around Unbounded_String, which
> doesn't need to be controlled, but then controlled extension would be
> heavier. Then the choice between private and interface amounts to
> whether or not it could be useful to use simultaneously several
> implementations of String_Holder in the same project. I cannot think of
> any project where it would be the case, so I would lean towards private,
> but maybe I'm lacking imagination here.
>
> Still under the same assumption, is the above specification sane, or am
> I missing something? Query procedure is probably not absolutely
> necessary, but I guess it can be occasionally useful to save a string
> copy compared to To_String, and it seems to be a very small
> implementation burden anyway.
>
> Still under the same assumption, can it be useful to provide unary "+"
> functions to tersely convert String_Holder to String, and maybe
> vice-versa, or would it do more harm (obfuscation) than good?
>
> And lastly, is there any trick to allow a String_Holder object or
> similar to be pre-elaborable?
>
> Thanks in advance for your insights,
> Natasha

Have you considered a "Flyweight"?

Here's an example in Ada2012 (which is soooo much easier to acheive
than in previous Ada versions).

The coffee flavour string is repeated in each order but only unique
strings are stored and each order context contains a reference to the
string.

In a real application, you'd want probably want to add finalization.

-- Martin



-- main.adb
with Applications; use Applications;
procedure Main is
   App : Application := Create;
begin
   App.Execute;
end Main;

-- applications.ads
        private with Ada.Containers.Vectors;
        private with Coffee_Orders.Flavours;
        private with Coffee_Orders.Flavours.Factories;
limited private with Coffee_Order_Contexts;
package Applications is
   type Application (<>) is tagged limited private;
   function Create return Application;
   procedure Execute (A : in out Application);
private
   use Coffee_Orders.Flavours.Factories;
   type Order is record
      Context : access Coffee_Order_Contexts.Coffee_Order_Context;
      Flavour : access Coffee_Orders.Flavours.Flavour;
   end record;
   package Order_Vectors is
      new Ada.Containers.Vectors (Natural, Order);
   type Application is tagged limited record
      Orders          : Order_Vectors.Vector;
      Flavour_Factory : Coffee_Orders.Flavours.Factories.Factory;
   end record;
   procedure Take_Orders (A       : in out Application;
                          Flavour :        String;
                          Table   :        Integer);
end Applications;

-- applications.adb
with Ada.Text_IO;            use Ada.Text_IO;
with Coffee_Order_Contexts;  use Coffee_Order_Contexts;
with Coffee_Orders.Flavours; use Coffee_Orders.Flavours;
package body Applications is
   function Create return Application is
   begin
      return Result : Application do
         null;
      end return;
   end Create;
   procedure Take_Orders (A       : in out Application;
                          Flavour :        String;
                          Table   :        Integer) is
   begin
      A.Orders.Append ((Context => new Coffee_Order_Context'(Create
(Table)),
                        Flavour =>
Flavour_Ref'(A.Flavour_Factory.Get_Flavour (Flavour))));
   end Take_Orders;
   procedure Execute (A : in out Application) is
   begin
      A.Take_Orders ("Cappuccino", 2);
      A.Take_Orders ("Cappuccino", 2);
      A.Take_Orders ("Frappe", 1);
      A.Take_Orders ("Frappe", 1);
      A.Take_Orders ("Xpresso", 1);
      A.Take_Orders ("Frappe", 897);
      A.Take_Orders ("Cappuccino", 97);
      A.Take_Orders ("Cappuccino", 97);
      A.Take_Orders ("Frappe", 3);
      A.Take_Orders ("Xpresso", 3);
      A.Take_Orders ("Cappuccino", 3);
      A.Take_Orders ("Xpresso", 96);
      A.Take_Orders ("Frappe", 552);
      A.Take_Orders ("Cappuccino", 121);
      A.Take_Orders ("Xpresso", 121);
      for Order of A.Orders loop
         Order.Flavour.Serve_Coffee (Order.Context.all);
      end loop;
      Put_Line ("Total Coffee_Flavor objects made:" & Integer'Image
(A.Flavour_Factory.Total_Flavours_Made));
   end Execute;
end Applications;

-- coffee_order_contexts.ads
package Coffee_Order_Contexts is
   type Coffee_Order_Context (<>) is tagged private;
   function Create (Table : Integer) return Coffee_Order_Context;
   function Table_No (COC : Coffee_Order_Context) return Integer;
private
   type Coffee_Order_Context is tagged record
      Table : Integer := 0;
   end record;
end Coffee_Order_Contexts;

-- coffee_order_contexts.adb
package body Coffee_Order_Contexts is
   function Create (Table : Integer) return Coffee_Order_Context is
   begin
      return Result : Coffee_Order_Context do
         Result.Table := Table;
      end return;
   end Create;
   function Table_No (COC : Coffee_Order_Context) return Integer is
   begin
      return COC.Table;
   end Table_No;
end Coffee_Order_Contexts;

-- coffee_order_contexts-vectors.ads
with Ada.Containers.Indefinite_Vectors;
package Coffee_Order_Contexts.Vectors is
   new Ada.Containers.Indefinite_Vectors (Natural,
Coffee_Order_Context);

-- coffee_orders.ads
with Coffee_Order_Contexts; use Coffee_Order_Contexts;
package Coffee_Orders is
   type Coffee_Order is interface;
   procedure Serve_Coffee (CO  : Coffee_Order;
                           COC : Coffee_Order_Context) is abstract;
end Coffee_Orders;

-- coffee_orders-flavours.ads
private with Ada.Strings.Unbounded;
        with Coffee_Order_Contexts; use Coffee_Order_Contexts;
package Coffee_Orders.Flavours is
   type Flavour (<>) is new Coffee_Order with private;
   type Flavour_Ref is access all Flavour'Class;
   function Create (Name : String) return Flavour;
   function "=" (L, R : Flavour) return Boolean;
   overriding
   procedure Serve_Coffee (F   : Flavour;
                           COC : Coffee_Order_Context);
private
   use Ada.Strings.Unbounded;
   type Flavour is new Coffee_Order with record
      Name : Unbounded_String;
   end record;
end Coffee_Orders.Flavours;

-- coffee_orders-flavours.adb
with Ada.Strings.Equal_Case_Insensitive;
with Ada.Text_IO; use Ada.Text_IO;
package body Coffee_Orders.Flavours is
   function Create (Name : String) return Flavour is
   begin
      return Result : Flavour do
         Result.Name := To_Unbounded_String (Name);
      end return;
   end Create;
   function "=" (L, R : Flavour) return Boolean is
   begin
      return Ada.Strings.Equal_Case_Insensitive (To_String (L.Name),
To_String (R.Name));
   end "=";
   procedure Serve_Coffee (F   : Flavour;
                           COC : Coffee_Order_Context) is
   begin
      Put_Line ("Serving Coffee flavor " & To_String (F.Name)
                & " to table number " & Integer'Image (COC.Table_No));
   end Serve_Coffee;
end Coffee_Orders.Flavours;

-- coffee_orders-flavours-vectors.ads
with Ada.Containers.Vectors;
package Coffee_Orders.Flavours.Vectors is
   new Ada.Containers.Vectors (Natural, Flavour_Ref);

-- coffee_orders-flavours-factories.ads
private with Ada.Containers.Indefinite_Hashed_Maps;
private with Ada.Strings.Equal_Case_Insensitive;
private with Ada.Strings.Hash_Case_Insensitive;
private with Ada.Strings.Unbounded;
package Coffee_Orders.Flavours.Factories is
   type Factory is tagged private;
   function Get_Flavour (F    : in out Factory;
                         Name :        String)
                         return not null access Flavour;
   function Total_Flavours_Made (F : Factory) return Natural;
private
   use Ada.Strings.Unbounded;
   package Maps is
     new Ada.Containers.Indefinite_Hashed_Maps (Key_Type        =>
String,
                                                Element_Type    =>
Flavour,
                                                Hash            =>
Ada.Strings.Hash_Case_Insensitive,
                                                Equivalent_Keys =>
Ada.Strings.Equal_Case_Insensitive);
   type Factory is tagged record
      Flavours : Maps.Map;
   end record;
end Coffee_Orders.Flavours.Factories;

-- coffee_orders-flavours-factories.adb
package body Coffee_Orders.Flavours.Factories is
   function Get_Flavour (F    : in out Factory;
                         Name :        String) return not null access
Flavour is
      use type Maps.Cursor;
      C : constant Maps.Cursor := F.Flavours.Find (Name);
   begin
      if C /= Maps.No_Element then
         return F.Flavours.Constant_Reference (Name).Element;
      end if;
      F.Flavours.Insert (Name, Create (Name));
      return F.Flavours.Constant_Reference (Name).Element;
   end Get_Flavour;
   function Total_Flavours_Made (F : Factory) return Natural is
   begin
      return Natural (F.Flavours.Length);
   end Total_Flavours_Made;
end Coffee_Orders.Flavours.Factories;



^ permalink raw reply	[relevance 7%]

* Re: Interrupts handling in ADA
  2011-12-13 15:07  0%     ` Simon Wright
@ 2011-12-13 15:23  0%       ` Ada BRL
  0 siblings, 0 replies; 200+ results
From: Ada BRL @ 2011-12-13 15:23 UTC (permalink / raw)


On 13 Dic, 15:07, Simon Wright <si...@pushface.org> wrote:
> Ada BRL <ada.brl.2...@gmail.com> writes:
> > On 10 Dic, 22:27, Simon Wright <si...@pushface.org> wrote:
> >> The spec might look like
>
> >>    with Ada.Containers.Vectors;
> >>    package Queueing is
> >>       type Message is new Integer;
> >>       package Queue_Data
> >>       is new Ada.Containers.Vectors (Index_Type => Natural,
> >>                                      Element_Type => Message);
> >>       protected Queue is
> >>          procedure Put (M : Message);
> >>          entry Get (M : out Message);
> >>       private
> >>          Buffer : Queue_Data.Vector;
> >>       end Queue;
> >>    end Queueing;
>
> >> and (as a hint) the body of the Get entry might start like
>
> >>       entry Get (M : out Message) when not Buffer.Is_Empty is
> >>       begin
> > Thank you for the reply!
>
> > Please tell me if I'm wrong:
>
> > - inside the main task I must use an accept statement "Get": by doing
>
> Nitpicks: I said 'main task', but you might not need an explicit task,
> because the main program runs in the context of the 'environment task'
> so can make tasking calls, be blocked etc just like any other task.

Ok, it's clear, the main function it's a task itself...

>
> Also, this isn't called an accept statement; it's an entry call. The way
> a task indicates it's prepared to accept an entry call is by an accept
> statement; protected objects are different. So if instead of Queue being
> protected it was a task (not something I'd recommend) the corresponding
> body part would have looked like
>
>    accept Get (M : out Message) when not Buffer.Is_Empty do

I haven't understood you...
What does it mean "declaring a protected task"? You would not
recommend it, ok, but what does it mean?
In the example above is the Buffer (member of main) the unique
protected object or the main function itself has to be declared as
protected?

Sorry but I'm beginning to loose the thread...



>
> > it, this means that the main task wait on this "barrier" until there
> > is something inside the protected object queue; when entry Get is
> > available (due to the incoming data), the main task is automatically
> > notified and it executes the Get function, isnt' it? So the entry /
> > accept paradigm is something like events in C?
> > So the main task doesn't has to constantly poll the queue; the entry /
> > accept statement do it by itself. Am I right?
>
> That's right (no comment on the 'events in C' part, though).




^ permalink raw reply	[relevance 0%]

* Re: Interrupts handling in ADA
  2011-12-13 12:47  0%   ` Ada BRL
@ 2011-12-13 15:07  0%     ` Simon Wright
  2011-12-13 15:23  0%       ` Ada BRL
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2011-12-13 15:07 UTC (permalink / raw)


Ada BRL <ada.brl.2011@gmail.com> writes:

> On 10 Dic, 22:27, Simon Wright <si...@pushface.org> wrote:

>> The spec might look like
>>
>>    with Ada.Containers.Vectors;
>>    package Queueing is
>>       type Message is new Integer;
>>       package Queue_Data
>>       is new Ada.Containers.Vectors (Index_Type => Natural,
>>                                      Element_Type => Message);
>>       protected Queue is
>>          procedure Put (M : Message);
>>          entry Get (M : out Message);
>>       private
>>          Buffer : Queue_Data.Vector;
>>       end Queue;
>>    end Queueing;
>>
>> and (as a hint) the body of the Get entry might start like
>>
>>       entry Get (M : out Message) when not Buffer.Is_Empty is
>>       begin

> Thank you for the reply!
>
> Please tell me if I'm wrong:
>
> - inside the main task I must use an accept statement "Get": by doing

Nitpicks: I said 'main task', but you might not need an explicit task,
because the main program runs in the context of the 'environment task'
so can make tasking calls, be blocked etc just like any other task.

Also, this isn't called an accept statement; it's an entry call. The way
a task indicates it's prepared to accept an entry call is by an accept
statement; protected objects are different. So if instead of Queue being
protected it was a task (not something I'd recommend) the corresponding
body part would have looked like

   accept Get (M : out Message) when not Buffer.Is_Empty do

> it, this means that the main task wait on this "barrier" until there
> is something inside the protected object queue; when entry Get is
> available (due to the incoming data), the main task is automatically
> notified and it executes the Get function, isnt' it? So the entry /
> accept paradigm is something like events in C?
> So the main task doesn't has to constantly poll the queue; the entry /
> accept statement do it by itself. Am I right?

That's right (no comment on the 'events in C' part, though).



^ permalink raw reply	[relevance 0%]

* Re: Interrupts handling in ADA
  2011-12-10 22:27  7% ` Simon Wright
@ 2011-12-13 12:47  0%   ` Ada BRL
  2011-12-13 15:07  0%     ` Simon Wright
  0 siblings, 1 reply; 200+ results
From: Ada BRL @ 2011-12-13 12:47 UTC (permalink / raw)


On 10 Dic, 22:27, Simon Wright <si...@pushface.org> wrote:
> "Ada @ BRL" <ada.brl.2...@gmail.com> writes:
>
> > The environment of ADA applcation is:
>
> Ada, please!
>
>
>
> > I have 4 tasks that execute at the same time:
> > one is the main task,
> > the other three execute a "read" from network (socket) function inside
> > their bodies (on the other side there's the C/C++ application with 3
> > network sockets).
> [...]
> > I want that when new data is available on one or more socket threads,
> > this / these threads somehow notify the main thread that data is
> > arrived and then safely send the data to it.
>
> First off, I'd use a Queue.
>
> The new Ada2012 standard includes a synchronised Queue, which would be
> just what you want out of the box, but you won't find that in the
> current compilers, so you'll need to roll your own.
>
> Starting from Ada.Containers.Vectors[1], the Queue abstraction would
> come from using Append to put new mesages on the queue, Is_Empty to
> check whether there's something to get from the queue, and First_Element
> followed by Delete_First to fetch the front element.
>
> You then need to wrap this container in a protected object[2], so that
> the updates from the different input tasks don't corrupt each other, and
> so that the main task can block until there's something to read. Use a
> Put procedure to post messages onto the queue, and a Get entry to read
> the next message or block if there isn't one.
>
> The spec might look like
>
>    with Ada.Containers.Vectors;
>    package Queueing is
>       type Message is new Integer;
>       package Queue_Data
>       is new Ada.Containers.Vectors (Index_Type => Natural,
>                                      Element_Type => Message);
>       protected Queue is
>          procedure Put (M : Message);
>          entry Get (M : out Message);
>       private
>          Buffer : Queue_Data.Vector;
>       end Queue;
>    end Queueing;
>
> and (as a hint) the body of the Get entry might start like
>
>       entry Get (M : out Message) when not Buffer.Is_Empty is
>       begin
>
> If your input messages are not all the same type (in Ada-speak, type
> Message is indefinite), things get more complicated; but let's cross
> that bridge only if we need to.
>
> [1]http://www.adaic.org/resources/add_content/standards/05rm/html/RM-A-1...
> [2]http://en.wikibooks.org/wiki/Ada_Programming/Tasking#Protected_types

Thank you for the reply!

Please tell me if I'm wrong:

- inside the main task I must use an accept statement "Get": by doing
it, this means that the main task wait on this "barrier" until there
is something inside the protected object queue; when entry Get is
available (due to the incoming data), the main task is automatically
notified and it executes the Get function, isnt' it? So the entry /
accept paradigm is something like events in C?
So the main task doesn't has to constantly poll the queue; the entry /
accept statement do it by itself. Am I right?

Thank everyone for the help!!!



^ permalink raw reply	[relevance 0%]

* Re: Interrupts handling in ADA
  @ 2011-12-10 22:27  7% ` Simon Wright
  2011-12-13 12:47  0%   ` Ada BRL
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2011-12-10 22:27 UTC (permalink / raw)


"Ada @ BRL" <ada.brl.2011@gmail.com> writes:

> The environment of ADA applcation is:

Ada, please!

> I have 4 tasks that execute at the same time:
> one is the main task,
> the other three execute a "read" from network (socket) function inside
> their bodies (on the other side there's the C/C++ application with 3
> network sockets).
[...]
> I want that when new data is available on one or more socket threads,
> this / these threads somehow notify the main thread that data is
> arrived and then safely send the data to it.

First off, I'd use a Queue.

The new Ada2012 standard includes a synchronised Queue, which would be
just what you want out of the box, but you won't find that in the
current compilers, so you'll need to roll your own.

Starting from Ada.Containers.Vectors[1], the Queue abstraction would
come from using Append to put new mesages on the queue, Is_Empty to
check whether there's something to get from the queue, and First_Element
followed by Delete_First to fetch the front element.

You then need to wrap this container in a protected object[2], so that
the updates from the different input tasks don't corrupt each other, and
so that the main task can block until there's something to read. Use a
Put procedure to post messages onto the queue, and a Get entry to read
the next message or block if there isn't one.

The spec might look like

   with Ada.Containers.Vectors;
   package Queueing is
      type Message is new Integer;
      package Queue_Data
      is new Ada.Containers.Vectors (Index_Type => Natural,
                                     Element_Type => Message);
      protected Queue is
         procedure Put (M : Message);
         entry Get (M : out Message);
      private
         Buffer : Queue_Data.Vector;
      end Queue;
   end Queueing;

and (as a hint) the body of the Get entry might start like

      entry Get (M : out Message) when not Buffer.Is_Empty is
      begin

If your input messages are not all the same type (in Ada-speak, type
Message is indefinite), things get more complicated; but let's cross
that bridge only if we need to.

[1]http://www.adaic.org/resources/add_content/standards/05rm/html/RM-A-18-2.html
[2]http://en.wikibooks.org/wiki/Ada_Programming/Tasking#Protected_types



^ permalink raw reply	[relevance 7%]

* Re: discriminant questions
  @ 2011-09-23 10:57  6%                                 ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2011-09-23 10:57 UTC (permalink / raw)


On 23.09.11 09:59, Dmitry A. Kazakov wrote:

> Can I declare an iterator object constant? What is the meaning of its
> "constantness" when the container gets manipulated? See a huge language
> problem here? An iterator can be immutable only if the container is. How do
> I express such stuff in the language?

Well, have one more level of indirection, and one aspect (i.e., only
two more kludges ;-)  Not sure whether the aspect can be checked at
compile time, though, or to what extent.

Compiling: const.adb (source file time stamp: 2011-09-23 10:27:42)

     1. with Ada.Containers.Vectors;
     2.
     3. procedure Const is
     4.
     5.    type E is (Mon, Bin, Ter);
     6.    subtype P is Positive range 1 .. 100;
     7.
     8.    package Vec is new Ada.Containers.Vectors
     9.      (Element_Type => E,
    10.       Index_Type => P);
    11.
    12.    type Const_Vector is access constant Vec.Vector;
    13.    type Const_Cursor is new Vec.Cursor
    14.      with Invariant => Has_Element (Const_Cursor);
    15.
    16.    procedure Change (Element : in out E) is
    17.    begin
    18.       if Element = E'Last then
    19. 	 Element := E'First;
    20.       else
    21. 	 Element := E'Succ (Element);
    22.       end if;
    23.    end Change;
    24.
    25.    function Frozen (V : Vec.Vector) return Const_Vector is
    26.    begin
    27.       return V'Unchecked_Access;
    28.    end Frozen;
    29.
    30.    Container : Vec.Vector;
    31.    Position  : Vec.Cursor;
    32.    Const_Container : Const_Vector;
    33. begin
    34.    Container.Append(Mon);
    35.    Container.Append(Ter);
    36.    Position := Container.First;
    37.    Vec.Update_Element (Container,
    38. 		       Position,
    39. 		       Process => Change'Access);
    40.    Const_Container := Frozen (Container);
    41.    Vec.Update_Element (Const_Container.all,
                                               |
        >>> actual for "Container" must be a variable

    42. 		       Position,
    43. 		       Process => Change'Access);
    44.
    45. end Const;
    46.
    47.
    48.

 48 lines: 1 error
gnatmake: "const.adb" compilation error

Compilation exited abnormally with code 4 at Fri Sep 23 10:27:53



^ permalink raw reply	[relevance 6%]

* Re: Properties
  2010-12-03 19:52  3%                   ` Properties Shark8
@ 2010-12-03 21:14  0%                     ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2010-12-03 21:14 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:75475874-cd6c-4e75-8a2f-7675ecf0864a@f20g2000vbc.googlegroups.com...
...
>It is somewhat irritating that you cannot initialize element to
>GUI_Base'Class directly.

You can do this with the Ada containers.

>Attempting the following
>   Package GUI_Vector is New Ada.Containers.Vectors
>( Element_Type => GUI_Base'Class, Index_Type => Positive );
>yields
>instantiation error at a-convec.ads:321
>"unconstrained element type in array declaration actual for
>"Element_Type" must be a definite subtype"

Right, but you are using the wrong container for this. Try the indefinite 
containers (designed specifically for this purpose):

Package GUI_Vector is New Ada.Containers.Indefinite_Vectors
   ( Element_Type => GUI_Base'Class, Index_Type => Positive );

This will work fine.

                              Randy.



What's wrong with say initializing Ada.Containers.Vector with Positive
=> Index and Element => Access_GUI_Base_Class*?

*Type Access_GUI_Base_Class is Access GUI_Base'Class;

It would be nice to throw a "Not null" in because storing a 'pointer'
to "not an object" is pretty dumb... but that gives this error-set:
warning: in instantiation at a-convec.adb:1196
warning: (Ada 2005) null-excluding objects must be initialized
warning: "Constraint_Error" will be raised at run time
warning: in instantiation at a-convec.adb:1209
warning: (Ada 2005) null-excluding objects must be initialized
warning: "Constraint_Error" will be raised at run time

It's almost as if it's saying that we couldn't ever use the container
exclusively like this:

Vector : GUI_Vector.Vector:= GUI_Vector.Empty_Vector;
Component_1 : Aliased GUI_Base'Class:= Make_Component( ... );
--...
Component_n : Aliased GUI_Base'Class:= Make_Component( ... );
begin
 Vector.Add( Component_1'Access );
--...
 Vector.Add( Component_n'Access );
--the work
end;

>This raises another question. Ada
> does not support abstract access types. You want a reference to the widget
> be a fat pointer transparent to all widget operations with automatic
> collection of widget objects. This almost works in Ada, but it is 
> extremely
> boring to do.

[snip]
> The bottom line, interfaces must be removed from Ada.
> Instead of that an interface must be made inheritable
> from any concrete type. This is the same idea as with
> abstract record, array etc types.

Wouldn't this be alleviated by two things:
Allowing INTERFACE [keyword] objects to have fields (properties as
I've described, or somesuch)?
Allowing objects some sort of self/this/me attribute where the result
is a Not Null Access to its classwide-type*? (Or am I misunderstanding
what you mean by the need for "a fat pointer transparent to all widget
operations"?)

*Or is this the equivalent of requiring all such variables to be
Aliased?

>
> type Widget_Handle is private Widget; -- Like the widget, but isn't
> private
> type Widget_Handle is new Ada.Limited_Controlled with record
> Ptr : access Widget;
> end record;
>
> For access types there must be delegation support, which should eliminate
> need in wrappers. There are other issues as well, like that "access 
> Widget"
> is purposely not "access Widget'Class."
>
> > Finally, I've been quite impressed with Delphi's Visual Component
> > Library (VCL).
>
> That's interesting, because we are using the VCL quite heavily. One of our
> customers explicitly ordered that. Now, my impression is opposite to 
> yours:
> it is safer, *quicker*, cleaner, an far more maintainable to develop GUI 
> in
> *raw* Windows API than in VCL. As a bonus, you can get rid of that awful
> Borland C++, use VC++ or gcc instead.

Oh, right, the VCL *WAS* ported-over-to/interfaced-with Borland's C
Builder. I'm utterly unfamiliar with that incarnation of the VCL as my
experience with it has been on the Delphi (Object Pascal) side.

But the problem is that wrapping the API calls, and management of the
returned references, in objects yields something similar-in-structure
to the VCL, no?

I'm not saying that things couldn't have been done better; they could
have. But for being a useful object-oriented GUI library tied to a
singular API (Windows) I think it's done pretty well.

The idea we've been kicking around about a truly portable GUI library
with attention to type-safety and [hopefully] prevention of Bad Things
(insofar as they can be prevented, thus your desire for a statically-
checked GUI library) is an order of magnitude more complex. -- Though
I myself would like to see just such a portable GUI library done in
Ada.

>
> > Microsoft's MFC and Java's JFC seem to have been
> > 'inspired' [or copied] from the VCL, but neither presents itself as
> > uniform & usable/mature [if you will] as the VCL.
>
> We dropped MFC long ago and never returned to it. We didn't use JFC, so I 
> cannot say anything about it.

Imagine the VCL, then take away all the inherited handling of events
and make them all purely java-interfaces (so in order to handle events
you have to create some class which implements the interface; this is
usually cone in-line/via-anonymous-class), and you basically have
something similar to the JFC. 





^ permalink raw reply	[relevance 0%]

* Re: Properties
  2010-12-03  9:05  0%                 ` Properties Dmitry A. Kazakov
@ 2010-12-03 19:52  3%                   ` Shark8
  2010-12-03 21:14  0%                     ` Properties Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Shark8 @ 2010-12-03 19:52 UTC (permalink / raw)


On Dec 3, 2:05 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> > Why not have an INTERFACE hierarchy in addition to the GUI_Object
> > hierarchy?
>
> Hmm, isn't it same? To me interface = abstract type.

Usually they are interchangeable, but INTERFACES are the only way in
Ada to do something akin to multiple inheritance: i.e. it is the only
way that we can synthesize a spin-box {an increase value button, a
decrease value button, and a numeric-value edit-box} from the leaves
of our elemental-GUI-component hierarchy w/o encapsulating the items
within an otherwise useless 'container' object.

   Type GUI_Base is interface;
   Procedure On_Basic_Event(Object : In Out GUI_Base'Class;
                            Event : In Basic_Event'Class
                           );

   Type Button is interface and GUI_base;
   Procedure On_Click( Object : In Out Button'Class;
                       Click  : In Click_Event'Class
                     );

   Type Edit_Box is interface and GUI_Base;
   Procedure On_Change( Object : In Out Edit_Box'Class;
                        Change : In Change_Event'Class
                      );

   -- ...

   Type Spin_Box_Object is New GUI_Base_Object and Button and Edit_box
with
      record
         --...
      end record;



> > Additionally, it could help with keeping the GUI_Object hierarchy
> > smaller as there are many GUI items which are themselves composed of
> > other GUI items. A scroll-bar, for example, has two distinct
> > interfaces: the Button[s] and the slider-bar.
>
> Ada should have had proper multiple inheritance 15 years ago.

Mayhaps; but that would be irrelevant to actual task. (i.e.  where
someone plops down and says to your boss "We're using Ada 2005 and we
want a GUI library fully and seamlessly portable across X, Y, and Z
OSes." who then turns to you and me and says "Make it!")

> > By "widget containers" do you mean something like
> > Ada.Containers.Vectors initialized to the classwide-type of the root
> > of the GUI_Object hierarchy, OR do you mean some component which
> > contains other components (like a panel, perhaps)? {I'm inclined to
> > believe you meant the latter.}
>
> Yes, the latter, but the former is also required, you frequently need lists
> of widgets (of referential semantics).

It is somewhat irritating that you cannot initialize element to
GUI_Base'Class directly.

Attempting the following
   Package GUI_Vector is New Ada.Containers.Vectors
	( Element_Type => GUI_Base'Class, Index_Type => Positive );
yields
instantiation error at a-convec.ads:321
"unconstrained element type in array declaration actual for
"Element_Type" must be a definite subtype"

What's wrong with say initializing Ada.Containers.Vector with Positive
=> Index and Element => Access_GUI_Base_Class*?

*Type Access_GUI_Base_Class is Access GUI_Base'Class;

It would be nice to throw a "Not null" in because storing a 'pointer'
to "not an object" is pretty dumb... but that gives this error-set:
warning: in instantiation at a-convec.adb:1196
warning: (Ada 2005) null-excluding objects must be initialized
warning: "Constraint_Error" will be raised at run time
warning: in instantiation at a-convec.adb:1209
warning: (Ada 2005) null-excluding objects must be initialized
warning: "Constraint_Error" will be raised at run time

It's almost as if it's saying that we couldn't ever use the container
exclusively like this:

Vector : GUI_Vector.Vector:= GUI_Vector.Empty_Vector;
Component_1 : Aliased GUI_Base'Class:= Make_Component( ... );
--...
Component_n : Aliased GUI_Base'Class:= Make_Component( ... );
begin
 Vector.Add( Component_1'Access );
--...
 Vector.Add( Component_n'Access );
--the work
end;

>This raises another question. Ada
> does not support abstract access types. You want a reference to the widget
> be a fat pointer transparent to all widget operations with automatic
> collection of widget objects. This almost works in Ada, but it is extremely
> boring to do.

[snip]
> The bottom line, interfaces must be removed from Ada.
> Instead of that an interface must be made inheritable
> from any concrete type. This is the same idea as with
> abstract record, array etc types.

Wouldn't this be alleviated by two things:
Allowing INTERFACE [keyword] objects to have fields (properties as
I've described, or somesuch)?
Allowing objects some sort of self/this/me attribute where the result
is a Not Null Access to its classwide-type*? (Or am I misunderstanding
what you mean by the need for "a fat pointer transparent to all widget
operations"?)

*Or is this the equivalent of requiring all such variables to be
Aliased?

>
>    type Widget_Handle is private Widget; -- Like the widget, but isn't
> private
>    type Widget_Handle is new Ada.Limited_Controlled with record
>        Ptr : access Widget;
>    end record;
>
> For access types there must be delegation support, which should eliminate
> need in wrappers. There are other issues as well, like that "access Widget"
> is purposely not "access Widget'Class."
>
> > Finally, I've been quite impressed with Delphi's Visual Component
> > Library (VCL).
>
> That's interesting, because we are using the VCL quite heavily. One of our
> customers explicitly ordered that. Now, my impression is opposite to yours:
> it is safer, *quicker*, cleaner, an far more maintainable to develop GUI in
> *raw* Windows API than in VCL. As a bonus, you can get rid of that awful
> Borland C++, use VC++ or gcc instead.

Oh, right, the VCL *WAS* ported-over-to/interfaced-with Borland's C
Builder. I'm utterly unfamiliar with that incarnation of the VCL as my
experience with it has been on the Delphi (Object Pascal) side.

But the problem is that wrapping the API calls, and management of the
returned references, in objects yields something similar-in-structure
to the VCL, no?

I'm not saying that things couldn't have been done better; they could
have. But for being a useful object-oriented GUI library tied to a
singular API (Windows) I think it's done pretty well.

The idea we've been kicking around about a truly portable GUI library
with attention to type-safety and [hopefully] prevention of Bad Things
(insofar as they can be prevented, thus your desire for a statically-
checked GUI library) is an order of magnitude more complex. -- Though
I myself would like to see just such a portable GUI library done in
Ada.

>
> > Microsoft's MFC and Java's JFC seem to have been
> > 'inspired' [or copied] from the VCL, but neither presents itself as
> > uniform & usable/mature [if you will] as the VCL.
>
> We dropped MFC long ago and never returned to it. We didn't use JFC, so I  cannot say anything about it.

Imagine the VCL, then take away all the inherited handling of events
and make them all purely java-interfaces (so in order to handle events
you have to create some class which implements the interface; this is
usually cone in-line/via-anonymous-class), and you basically have
something similar to the JFC.



^ permalink raw reply	[relevance 3%]

* Re: Properties
  2010-12-03  5:53  4%               ` Properties Shark8
@ 2010-12-03  9:05  0%                 ` Dmitry A. Kazakov
  2010-12-03 19:52  3%                   ` Properties Shark8
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2010-12-03  9:05 UTC (permalink / raw)


On Thu, 2 Dec 2010 21:53:13 -0800 (PST), Shark8 wrote:

> On Dec 1, 8:59�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>>The main problem is the interface of such a library. There are
>>multiple parallel hierarchies need to be handled: a hierarchy
>>of widget types, a hierarchy of widget containers, a hierarchy
>>of event handlers (events are filtered, propagated, swallowed,
>>re-generated).
>>
> Why not have an INTERFACE hierarchy in addition to the GUI_Object
> hierarchy?

Hmm, isn't it same? To me interface = abstract type.

> Additionally, it could help with keeping the GUI_Object hierarchy
> smaller as there are many GUI items which are themselves composed of
> other GUI items. A scroll-bar, for example, has two distinct
> interfaces: the Button[s] and the slider-bar.

Ada should have had proper multiple inheritance 15 years ago.
 
> By "widget containers" do you mean something like
> Ada.Containers.Vectors initialized to the classwide-type of the root
> of the GUI_Object hierarchy, OR do you mean some component which
> contains other components (like a panel, perhaps)? {I'm inclined to
> believe you meant the latter.}

Yes, the latter, but the former is also required, you frequently need lists
of widgets (of referential semantics). This raises another question. Ada
does not support abstract access types. You want a reference to the widget
be a fat pointer transparent to all widget operations with automatic
collection of widget objects. This almost works in Ada, but it is extremely
boring to do. The scheme is as follows:

1. You declare a separate interface type for each widget
2. You implement the interface by the widget object
3. You implement the interface by the handle to the widget (a controlled
type).

It is nightmare to do, I know it. I did so in one project (not for the
widgets), and I don't want this adventure anymore.

The bottom line, interfaces must be removed from Ada. Instead of that an
interface must be made inheritable from any concrete type. This is the same
idea as with abstract record, array etc types. Any type has interface,
which is inheritable without the implementation:

   type Widget_Handle is private Widget; -- Like the widget, but isn't
private
   type Widget_Handle is new Ada.Limited_Controlled with record
       Ptr : access Widget;
   end record;

For access types there must be delegation support, which should eliminate
need in wrappers. There are other issues as well, like that "access Widget"
is purposely not "access Widget'Class."

> Finally, I've been quite impressed with Delphi's Visual Component
> Library (VCL).

That's interesting, because we are using the VCL quite heavily. One of our
customers explicitly ordered that. Now, my impression is opposite to yours:
it is safer, *quicker*, cleaner, an far more maintainable to develop GUI in
*raw* Windows API than in VCL. As a bonus, you can get rid of that awful
Borland C++, use VC++ or gcc instead.

> Microsoft's MFC and Java's JFC seem to have been
> 'inspired' [or copied] from the VCL, but neither presents itself as
> uniform & usable/mature [if you will] as the VCL.

We dropped MFC long ago and never returned to it. We didn't use JFC, so I
cannot say anything about it.

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



^ permalink raw reply	[relevance 0%]

* Re: Properties
  @ 2010-12-03  5:53  4%               ` Shark8
  2010-12-03  9:05  0%                 ` Properties Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Shark8 @ 2010-12-03  5:53 UTC (permalink / raw)


On Dec 1, 8:59 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
>The main problem is the interface of such a library. There are
>multiple parallel hierarchies need to be handled: a hierarchy
>of widget types, a hierarchy of widget containers, a hierarchy
>of event handlers (events are filtered, propagated, swallowed,
>re-generated).
>
> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de

Why not have an INTERFACE hierarchy in addition to the GUI_Object
hierarchy? This would allow for an easy way for foreign-language
objects to be incorporated, to some extent, into applications which
use this hypothetical library.... with only the added encumberment of
forcing more up-front design. (Usu. a good thing.)

Additionally, it could help with keeping the GUI_Object hierarchy
smaller as there are many GUI items which are themselves composed of
other GUI items. A scroll-bar, for example, has two distinct
interfaces: the Button[s] and the slider-bar.

The event-handler hierarchy seems to be the most 'interesting', not
because of the events themselves, but because of the problem of how
best to hook them; as you said they can be consumed, passed-through,
emitted, and so-forth. They should, therefore be lightweight (as we
don't want to transmit unnecessary information), quick in construction
(this will impact the GUIs responsiveness) and clean in destruction
(no memory leaks, please).

By "widget containers" do you mean something like
Ada.Containers.Vectors initialized to the classwide-type of the root
of the GUI_Object hierarchy, OR do you mean some component which
contains other components (like a panel, perhaps)? {I'm inclined to
believe you meant the latter.}

Finally, I've been quite impressed with Delphi's Visual Component
Library (VCL). Microsoft's MFC and Java's JFC seem to have been
'inspired' [or copied] from the VCL, but neither presents itself as
uniform & usable/mature [if you will] as the VCL. While the VCL
doesn't use interfaces it does make nice use of properties; event
handlers are get/set w/ properties and handlers are not required to be
installed for every object like they are in Java; I believe that
internally Delphi uses something like this:
If Assigned(Handler) Then Handler^(Sender); {Assigned tests for null.}



^ permalink raw reply	[relevance 4%]

* Re: Callback in Ada
  @ 2010-11-27 10:22  4% ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2010-11-27 10:22 UTC (permalink / raw)


Georg Maubach writes:
> Hi All,
>
> today I learnt what a callback function is and also how it is used in 
> Python. I have tested the following code which runs in Python:
>
> def apply_to (function, valueList):
>    resultList = []
>
>    if __debug__: print "Calling function ", function
>    
>    for value in valueList:
>       if __debug__: print "value: ", value
>       r = function (value)
>       if __debug__: print "result: ", r
>       resultList.append(r)
>
>    return resultList

This function "apply_to" is a classic example of a "passive iterator".

This example is not type-safe; apply_to assumes that function takes
exactly one argument and returns exactly one result.  What happens if
you pass a function that takes zero or two arguments? Or if it does not
return anything?

> How would I do that in Ada?

There are several ways, most of them type-safe.

Statically compiled, see ARM 12.1(24) for this example:

     generic
        type Item   is private;
        type Vector is array (Positive range <>) of Item;
        with function Sum(X, Y : Item) return Item;
     package On_Vectors is
        function Sum  (A, B : Vector) return Vector;
        function Sigma(A    : Vector) return Item;
        Length_Error : exception;
     end On_Vectors;

The body is in 12.2 and an example instantiation in 12.3(25).

The Ada containers library provides several examples of dynamically
bound callbacks, e.g. in Ada.Containers.Vectors (A.18.2(74/2)):

        procedure  Iterate
          (Container : in Vector;
           Process   : not null access procedure (Position : in Cursor));

The above is another classic example of a passive iterator.

In both of these cases, the compiler enforces type safety between the
elements in the vector, the arguments passed to the function, etc.  In
the static (generic) case, the compiler makes it impossible to call the
iterator without a callback; in the dynamic case, the compiler cannot
always check at compile time, so it inserts a run-time check.

A third, type-unsafe way to pass callbacks, is to use addresses, e.g:

type Array_Of_Items is array (Positive range <>) of Item;
procedure For_Each_Element (Of_Array : in Array_Of_Items;
                            Action   : in System.Address) is
   procedure Act (On_Item : in out Item; At_Index : in Positive);
   for Act'Address use Action;
begin
   for J in Of_Array'Range loop
      Act (On_Item => On_Array (J), At_Index => J);
   end loop;
end For_Each_Element;

Apart from passive iterators, callbacks are heavily used in GUI
programming.  You can find many examples of callbacks in the
"slot/signal" model of GtkAda.

There are alternatives to callbacks; for example I believe Claw and Qt
use overriding primitive operations instead of callbacks.

-- 
Ludovic Brenta.



^ permalink raw reply	[relevance 4%]

* Re: Do people who use Ada also use ocaml or F#?
  @ 2010-11-06 20:56  4%                   ` Robert A Duff
  0 siblings, 0 replies; 200+ results
From: Robert A Duff @ 2010-11-06 20:56 UTC (permalink / raw)


Stephen Leake <stephen_leake@stephe-leake.org> writes:

> Robert A Duff <bobduff@shell01.TheWorld.com> writes:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>
>>> How do you execute a generic body? Testable are generic instances.
>>
>>     You can't test a generic without instantiating it.
>>     
>>     You can't test a procedure without calling it.
>>     
>>     You can't test an abstract type without declaring
>>     a concrete type, and some objects of that type.
>>
>> What am I missing?
>
> To truly test a generic, you need to test with all possible
> instantiations.

To "truly" test a procedure, you have to call it with all
possible parameter values (and all possible globals,
if it uses those).

> Or at least with a representative subset.

Right, it's usually impossible to try all possibilities,
so we pick some subset -- for generics and for procedures.

>...If the generic parameters are
> well structured, it may be possible to show that a few instances are
> sufficient.

For something like Ada.Containers.Vectors, it's fairly easy
to know that the code doesn't much care what the element type is.

If you find a bug in a generic, it is almost certainly
a bug in every instance, in my experience.  Only rarely
does the bug depend on specific properties of some
instance.

> That's much more effort than testing a single concrete procedure.

Well, I agree that testing a generic is typically harder
than testing a single procedure.  That's because generics
are typically more, um, "general".  But the claim was
that generics are untestable, which seems too extreme to me.
And if you replace generics with some other feature,
then if that feature has the generality desired,
it will be equally hard to test.

> It may be worth it, of course; I often use generics precisely to reduce
> testing burden.

Right, it's certainly easier to test a generic, than to write
similar code 20 times for 20 different types, and test all of
those.  Just like it's easier to test a single procedure than to
test 20 cut&pasted versions of the same code (each of which
has been slightly modified so they're not quite identical
anymore).

- Bob



^ permalink raw reply	[relevance 4%]

* Re: S-expression I/O in Ada
    2010-08-01 18:25  6% ` Jeffrey Carter
  @ 2010-08-27 13:19  3% ` Natasha Kerensikova
  2 siblings, 0 replies; 200+ results
From: Natasha Kerensikova @ 2010-08-27 13:19 UTC (permalink / raw)


Hello,

Here is my third attempt, hopefully avoiding the mistakes I did before.

I wanted to have a go at an access-based implementation, and while it
seems to end up without roughly the same complexity as my previous
Doubly_Linked_List-based attempt, I felt incredibly much more at home
with it. Is it genuinely more simple in some way, or is it just my
pointer-juggling experience from C?

The interface is relatively limited, but it's enough for all the needs I
ever had. 

The limited interface long with the Container objects make me pretty
confident in the correctness of the memory management.

I'm still not satisfied with the indentation, it still feels much too
shallow for my tastes, and the general look of my sources feels it needs
much more spacing out.


As usual, all comments that can help me writing better Ada code and/or
becoming a better Ada noob are warmly welcome.

Thanks in advance for your help,
Natasha




with Ada.Finalization;

private with Ada.Containers.Vectors;



package Sexp is

   type Container is tagged limited private;
      -- container that keeps tracks of allocated data

   type Cursor is private;
      -- object that refers to a S-expression node
      -- it's the only way a client can interact with S-expression contents

   type Node_Kind is (Atom_Node, List_Node);
      -- a node is either an atom or a list

   type Octet is range 0 .. 255;
   type Atom_Data is array (Positive range <>) of Octet;
      -- publicly defined to allow object conversion anywhere



   ---------------
   -- Constants --
   ---------------

   No_Element : constant Cursor;



   ---------------------
   -- Atom converters --
   ---------------------

   procedure Atom_To_String(Data : in Atom_Data; Image : out String);
   procedure String_To_Atom(Image : in String; Data : out Atom_Data);
      -- conversion between existing objects, assumed to be of equal length

   function To_String(Data : in Atom_Data) return String;
   function To_Atom(Image : in String) return Atom_Data;
      -- constructing one type from the other



   -----------------------
   -- Container methods --
   -----------------------

   procedure Reset(Universe : in out Container);
      -- reset the container using an empty list node as the new root
   procedure Reset(Universe : in out Container; Root_Atom : in Atom_Data);
      -- reset the container using the given atom data as root
   procedure Reset(Universe : in out Container; Root_Atom : in String);
      -- reset the container using the given string as root atom



   -----------------------
   -- Cursor management --
   -----------------------

   function Root(From : in Container) return Cursor;

   function Next(Position : in Cursor) return Cursor;
   procedure Next(Position : in out Cursor);



   --------------------
   -- Node accessors --
   --------------------

   function Is_Atom(Position : in Cursor) return Boolean;
   function Is_List(Position : in Cursor) return Boolean;

   function Kind(Position : in Cursor) return Node_Kind;
      -- raise Constraint_Error when Position is No_Element



   --------------------
   -- Atom accessors --
   --------------------
      -- They all raise Constraint_Error when the given Cursor does not refer
      -- to an atom node.

   function To_Atom(Position : in Cursor) return Atom_Data;
   function To_String(Position : in Cursor) return String;

   procedure Query_Atom
     (Position : in Cursor;
      Process  : not null access procedure(Data : in Atom_Data));

   function Atom_Length(Position : in Cursor) return Natural;


   -------------------
   -- List accessor --
   -------------------

   function Sublist(Position : in Cursor) return Cursor;
      -- raise Constraint_Error when Position does not refer to a list



   -----------------------
   -- Node constructors --
   -----------------------
      -- They all raise Constraint_Error when Position is No_Element

   procedure Append_Empty_List
     (Universe : in out Container;
      Position : in     Cursor);

   procedure Append
     (Universe : in out Container;
      Position : in     Cursor;
      Atom     : in     Atom_Data);

   procedure Append
     (Universe : in out Container;
      Position : in     Cursor;
      Image    : in     String);



   ---------------
   -- Iterators --
   ---------------

   procedure Iterate
     (Start        : in Cursor;
      Process_Atom : access procedure(Data : in Atom_Data);
      Process_List : access procedure(First : in Cursor));

   procedure Iterate_Over_Atoms
     (Start   : in Cursor;
      Process : not null access procedure(Data : in Atom_Data));

   procedure Iterate_Over_Lists
     (Start   : in Cursor;
      Process : not null access procedure(First : in Cursor));

   procedure Iterate_Over_Commands
     (Start   : in Cursor;
      Execute : not null access procedure(Command   : in String;
                                          Arguments : in Cursor));



private

   ----------------------
   -- Type definitions --
   ----------------------

   type Node(<>);
   type Atom_Access is access Atom_Data;
   type Node_Access is access Node;

   type Node (Kind : Node_Kind) is
      record
         Next : Node_Access;
         case Kind is
            when Atom_Node => Atom  : Atom_Access;
            when List_Node => Child : Node_Access;
         end case;
      end record;

   package Nodes is
      new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Node_Access);

   package Atoms is
      new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Atom_Access);

   type Container is
      new Ada.Finalization.Limited_Controlled with record
         List_Node : Nodes.Vector;
         Atom_List : Atoms.Vector;
         Root      : Node_Access;
      end record;

   type Cursor is
      record
         Parent : Node_Access;
         Node   : Node_Access;
      end record;



   -----------------------
   -- Container methods --
   -----------------------

   procedure Clean_Atoms(Universe : in out Container);
   procedure Clean_Nodes(Universe : in out Container);

   overriding
   procedure Finalize(This : in out Container);

   procedure Make_Atom
     (Maker : in out Container;
      Atom  :    out Atom_Access;
      Data  : in     Atom_Data);

   procedure Make_Atom
     (Maker : in out Container;
      Atom  :    out Atom_Access;
      Image : in     String);

   procedure Make_Node
     (Maker : in out Container;
      Node  :    out Node_Access;
      Kind  : in     Node_Kind);

   procedure Make_Node_Atom
     (Maker : in out Container;
      Node  :    out Node_Access;
      Data  : in     Atom_Data);

   procedure Make_Node_Atom
     (Maker : in out Container;
      Node  :    out Node_Access;
      Image : in     String);

   procedure Make_Node_List
     (Maker  : in out Container;
      Node   :    out Node_Access;
      Child  : in     Node_Access := null);



   ---------------
   -- Constants --
   ---------------

   No_Element : constant Cursor := (Parent => null, Node => null);

end Sexp;





with Ada.Unchecked_Deallocation;



package body Sexp is

   procedure Free is
      new Ada.Unchecked_Deallocation(Node, Node_Access);

   procedure Free is
      new Ada.Unchecked_Deallocation(Atom_Data, Atom_Access);



   ------------------------------------
   -- String vs Atom_Data converters --
   ------------------------------------

   procedure String_To_Atom(Image : in String; Data : out Atom_Data) is
   begin
      for i in Image'Range loop
         Data(i - Image'First + Data'First) := Character'Pos(Image(i));
      end loop;
   end String_To_Atom;



   procedure Atom_To_String(Data : in Atom_Data; Image : out String) is
   begin
      for i in Data'Range loop
         Image(i - Data'First + Image'First) := Character'Val(Data(i));
      end loop;
   end Atom_To_String;



   function To_Atom(Image : in String) return Atom_Data is
      Data : Atom_Data(1 .. Image'Length);
   begin
      String_To_Atom(Image, Data);
      return Data;
   end To_Atom;



   function To_String(Data : in Atom_Data) return String is
      Image : String(Data'Range);
   begin
      Atom_To_String(Data, Image);
      return Image;
   end To_String;



   -------------------------------
   -- Container private methods --
   -------------------------------


   procedure Clean_Atoms(Universe : in out Container) is
      Current : Atoms.Cursor := Atoms.First(Universe.Atom_List);
      Atom : Atom_Access;
   begin
      while Atoms.Has_Element(Current) loop
         Atom := Atoms.Element(Current);
         Free(Atom);
         Atoms.Next(Current);
      end loop;
      Atoms.Clear(Universe.Atom_List);
   end Clean_Atoms;



   procedure Clean_Nodes(Universe : in out Container) is
      Current : Nodes.Cursor := Nodes.First(Universe.List_Node);
      Node : Node_Access;
   begin
      while Nodes.Has_Element(Current) loop
         Node := Nodes.Element(Current);
         Free(Node);
         Nodes.Next(Current);
      end loop;
      Nodes.Clear(Universe.List_Node);
   end Clean_Nodes;



   overriding
   procedure Finalize(This : in out Container) is
   begin
      Clean_Nodes(This);
      Clean_Atoms(This);
   end Finalize;



   procedure Make_Atom
     (Maker : in out Container;
      Atom  :    out Atom_Access;
      Data  : in     Atom_Data) is
   begin
      Atom := new Atom_Data(Data'Range);
      Atom.All := Data;
      Atoms.Append(Maker.Atom_List, Atom);
   end Make_Atom;



   procedure Make_Atom
     (Maker : in out Container;
      Atom  :    out Atom_Access;
      Image : in     String) is
   begin
      Atom := new Atom_Data(1 .. Image'Length);
      String_To_Atom(Image, Atom.All);
      Atoms.Append(Maker.Atom_List, Atom);
   end Make_Atom;



   procedure Make_Node
     (Maker : in out Container;
      Node  :    out Node_Access;
      Kind  : in     Node_Kind) is
   begin
      Node := new Sexp.Node(Kind);
      Nodes.Append(Maker.List_Node, Node);
   end Make_Node;



   procedure Make_Node_Atom
     (Maker : in out Container;
      Node  :    out Node_Access;
      Data  : in     Atom_Data) is
   begin
      Make_Node(Maker, Node, Atom_Node);
      Make_Atom(Maker, Node.Atom, Data);
   end Make_Node_Atom;



   procedure Make_Node_Atom
     (Maker : in out Container;
      Node  :    out Node_Access;
      Image : in     String) is
   begin
      Make_Node(Maker, Node, Atom_Node);
      Make_Atom(Maker, Node.Atom, Image);
   end Make_Node_Atom;



   procedure Make_Node_List
     (Maker  : in out Container;
      Node   :    out Node_Access;
      Child  : in     Node_Access := null) is
   begin
      Make_Node(Maker, Node, List_Node);
      Node.Child := Child;
   end Make_Node_List;



   ------------------------------
   -- Container public methods --
   ------------------------------


   procedure Reset(Universe : in out Container) is
   begin
      Clean_Nodes(Universe);
      Clean_Atoms(Universe);
      Make_Node_List(Universe, Universe.Root);
   end Reset;



   procedure Reset(Universe : in out Container; Root_Atom : in Atom_Data) is
   begin
      Clean_Nodes(Universe);
      Clean_Atoms(Universe);
      Make_Node_Atom(Universe, Universe.Root, Root_Atom);
   end Reset;



   procedure Reset(Universe : in out Container; Root_Atom : in String) is
   begin
      Clean_Nodes(Universe);
      Clean_Atoms(Universe);
      Make_Node_Atom(Universe, Universe.Root, Root_Atom);
   end Reset;



   -----------------------
   -- Cursor management --
   -----------------------

   function Root(From : in Container) return Cursor is
      Result : Cursor := (Parent => null, Node => From.Root);
   begin
      return Result;
   end Root;



   function Next(Position : in Cursor) return Cursor is
      Result : Cursor := No_Element;
   begin
      if Position.Node /= null and then Position.Node.Next /= null then
         Result.Parent := Position.Node;
         Result.Node   := Position.Node.Next;
      end if;
      return Result;
   end Next;



   procedure Next(Position : in out Cursor) is
   begin
      if Position.Node /= null then
         if Position.Node.Next /= null then
            Position.Parent := Position.Node;
            Position.Node   := Position.Parent.Next;
         else
            Position := No_Element;
         end if;
      end if;
   end Next;



   --------------------
   -- Node accessors --
   --------------------


   function Is_Atom(Position : in Cursor) return Boolean is
   begin
      return Position.Node /= null and then Position.Node.Kind = Atom_Node;
   end Is_Atom;



   function Is_List(Position : in Cursor) return Boolean is
   begin
      return Position.Node /= null and then Position.Node.Kind = List_Node;
   end Is_List;



   function Kind(Position : in Cursor) return Node_Kind is
   begin
      if Position.Node = null then
         raise Constraint_Error with "Position cursor has no element";
      end if;
      return Position.Node.Kind;
   end Kind;



   --------------------
   -- Atom accessors --
   --------------------


   function To_Atom(Position : in Cursor) return Atom_Data is
   begin
      if not Is_Atom(Position) then
         raise Constraint_Error with "Position cursor is not an atom";
      end if;
      return Position.Node.Atom.all;
   end To_Atom;



   function To_String(Position : in Cursor) return String is
   begin
      if not Is_Atom(Position) then
         raise Constraint_Error with "Position cursor is not an atom";
      end if;
      return To_String(Position.Node.Atom.all);
   end To_String;



   procedure Query_Atom
     (Position : in Cursor;
      Process  : not null access procedure(Data : in Atom_Data)) is
   begin
      if not Is_Atom(Position) then
         raise Constraint_Error with "Position cursor is not an atom";
      end if;
      Process(Position.Node.Atom.all);
   end Query_Atom;



   function Atom_Length(Position : in Cursor) return Natural is
   begin
      if not Is_Atom(Position) then
         raise Constraint_Error with "Position cursor is not an atom";
      end if;
      return Position.Node.Atom'Length;
   end Atom_Length;



   -------------------
   -- List accessor --
   -------------------


   function Sublist(Position : in Cursor) return Cursor is
      Result : Cursor;
   begin
      if not Is_List(Position) then
         raise Constraint_Error with "Position cursor is not a list";
      end if;
      Result.Parent := Position.Node;
      Result.Node   := Position.Node.Child;
      return Result;
   end Sublist;



   -----------------------
   -- Node constructors --
   -----------------------


   procedure Append_Empty_List
     (Universe : in out Container;
      Position : in     Cursor)
   is
      Current : Node_Access := Position.Node;
   begin
      if Current /= null then
         raise Constraint_Error with "Position cursor has no element";
      end if;
      while Current.Next /= null loop
         Current := Current.Next;
      end loop;
      Make_Node_List(Universe, Current.Next);
   end Append_Empty_List;



   procedure Append
     (Universe : in out Container;
      Position : in     Cursor;
      Atom     : in     Atom_Data)
   is
      Current : Node_Access := Position.Node;
   begin
      if Current /= null then
         raise Constraint_Error with "Position cursor has no element";
      end if;
      while Current.Next /= null loop
         Current := Current.Next;
      end loop;
      Make_Node_Atom(Universe, Current.Next, Atom);
   end Append;



   procedure Append
     (Universe : in out Container;
      Position : in     Cursor;
      Image    : in     String)
   is
      Current : Node_Access := Position.Node;
   begin
      if Current /= null then
         raise Constraint_Error with "Position cursor has no element";
      end if;
      while Current.Next /= null loop
         Current := Current.Next;
      end loop;
      Make_Node_Atom(Universe, Current.Next, Image);
   end Append;



   ---------------
   -- Iterators --
   ---------------

   procedure Iterate
     (Start        : in Cursor;
      Process_Atom : access procedure(Data : in Atom_Data);
      Process_List : access procedure(First : in Cursor))
   is
      Current : Node_Access := Start.Node;
      First   : Cursor;
   begin
      if Process_Atom = null then
         if Process_List /= null then
            Iterate_Over_Lists(Start, Process_List);
         end if;
      elsif Process_List = null then
         Iterate_Over_Atoms(Start, Process_Atom);
      else
         while Current /= null loop
            case Current.Kind is
               when Atom_Node =>
                  Process_Atom(Current.Atom.all);
               when List_Node =>
                  First.Parent := Current;
                  First.Node   := Current.Child;
                  Process_List(First);
            end case;
            Current := Current.Next;
         end loop;
      end if;
   end Iterate;



   procedure Iterate_Over_Atoms
     (Start   : in Cursor;
      Process : not null access procedure(Data : in Atom_Data))
   is
      Current : Node_Access := Start.Node;
   begin
      while Current /= null loop
         if Current.Kind = Atom_Node then
            Process(Current.Atom.all);
         end if;
      end loop;
   end Iterate_Over_Atoms;



   procedure Iterate_Over_Lists
     (Start   : in Cursor;
      Process : not null access procedure(First : in Cursor))
   is
      Current : Node_Access := Start.Node;
      First   : Cursor;
   begin
      while Current /= null loop
         if Current.Kind = List_Node then
            First.Parent := Current;
            First.Node   := Current.Child;
            Process(First);
         end if;
      end loop;
   end Iterate_Over_Lists;



   procedure Iterate_Over_Commands
     (Start   : in Cursor;
      Execute : not null access procedure(Command   : in String;
                                          Arguments : in Cursor))
   is
      Current : Node_Access := Start.Node;
      Arg : Cursor;
   begin
      while Current /= null loop
         if Current.Kind = Atom_Node then
            Execute(To_String(Current.Atom.all), No_Element);
         elsif Current.Child.Kind = Atom_node then
            Arg.Parent := Current.Child;
            Arg.Node   := Current.Child.Next;
            Execute(To_String(Current.Child.Atom.all), Arg);
         end if;
      end loop;
   end Iterate_Over_Commands;

end Sexp;



^ permalink raw reply	[relevance 3%]

* Re: S-expression I/O in Ada
  2010-08-17 19:00  5%   ` Jeffrey Carter
@ 2010-08-18 10:49  0%     ` Natasha Kerensikova
  0 siblings, 0 replies; 200+ results
From: Natasha Kerensikova @ 2010-08-18 10:49 UTC (permalink / raw)


On 2010-08-17, Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> wrote:
> It seemed to me that you could implement this without any access types or 
> values, so I gave it a shot. The following has been compiled:
>
> private with Ada.Containers.Indefinite_Vectors;
> private with Ada.Containers.Vectors;

I have indeed forgotten about Ada containers. However after having read
A.18.2 and A.18.3, it seems to me that Doubly_Linked_Lists are more
appropriate than vectors: the recursive structure of S-expressions can
make assignment (i.e. deep copies) quite expensive, and
Doubly_Linked_Lists seem designed primarily to avoid copy of contained
objects (though I may be mistaken). Usual operations on S-expressions
are append and traversal, on which Vectors don't provide a significant
improvement (unlike e.g. random access).

Does it make sense or am I missing something?

Btw reading A.18 I discovered the idea of Cursor types, which I find
very nice: I'm used (in C) to hand over Nodes because they also contain
enough information to progress in the S-expression structure, but it
looks like Cursor would do it in a more Ada-ish way.

>     generic -- Object_Conversions
>        type Element (<>) is limited private;
>     package Object_Conversions is
>        function To_Atom (Value : in Element) return Atom;
>        function To_Object (Value : in Atom) return Element;
>     end Object_Conversions;

I'm not fond of that part, because it's actually a memory dump, while
atom contents are supposed to be a serialized representation of
(atomic) objects.

I'm aware that it's best to hide as much as possible about type
definitions, but I think in that particular case having Atom definition
public is justified.

The idea is that my other objects, clients of S_Expressions, will be
able to make a S-expression representing themselves. So they will need
subprograms to make S-expressions. Complex objects will only have to use
the container aspect of S-expressions, assembling S-expression
representation provided by their sub-objects. But at some point some
objects will be simple enough to be represented as atoms, and knowledge
about how to serialize these atomic objects into atom objects can't be
part of S_Expressions. Which means S_Expressions has to expose details
of atom type.

On the other hand, there will be relatively few atomic objects compared
to complex objects. Would it possible to hide atom type definition in a
subpackage or something, that would only be with'ed in atomic object
packages?

Maybe something like:
private with S_Expressions.Atoms;
package S_Expressions is
   type Atom is private;
   ...

It doesn't seem to work due to a circular dependency. But there anything
to do along that line of thoughts?

>     type Root is tagged null record;
>
>     package Lists is new Ada.Containers.Indefinite_Vectors (Index_Type => 
> Positive, Element_Type => Root'Class);
>
>     type S_Expression (Is_Atom : Boolean) is new Root with record
>        case Is_Atom is
>        when False =>
>           List : Lists.Vector;
>        when True =>
>           Value : Atom;
>        end case;
>     end record;

I don't understand why you need Indefinite_Vectors here. They have been
presented to me as heterogeneous vector containers, but here Lists would
be homogeneous, containing only S_Expression items.
I'm not sure about the need of Root either, but my guess is that it's to
provide a common root to all objects contained in the
Indefinite_Vectors.

But what makes S_Expression an indefinite type?



Thanks a lot for your review,
Natacha



^ permalink raw reply	[relevance 0%]

* Re: S-expression I/O in Ada
  @ 2010-08-17 19:00  5%   ` Jeffrey Carter
  2010-08-18 10:49  0%     ` Natasha Kerensikova
  0 siblings, 1 reply; 200+ results
From: Jeffrey Carter @ 2010-08-17 19:00 UTC (permalink / raw)


On 08/17/2010 10:01 AM, Natasha Kerensikova wrote:
>
> Even though I'm much more used to C than to Ada, I have the feeling it's
> horribly ugly and that using access types all over the place like I did
> is extremely poor. Yet I just can't find out exactly how it's wrong, nor
> how to get it right.

I would agree. Access types and values should not appear in the visible part of 
a package specification if at all possible.

> Would any other you be kind enough to have a look at it, and point me
> where I did wrong and explain me how wrong it is, be it on high-level
> package design to low-level implementation choice and anything in
> between including code style.

It seemed to me that you could implement this without any access types or 
values, so I gave it a shot. The following has been compiled:

private with Ada.Containers.Indefinite_Vectors;
private with Ada.Containers.Vectors;

package S_Expressions is
    type Atom is private;

    function To_Atom (Value : in String) return Atom;
    function To_String (Value : in Atom) return String;

    generic -- Object_Conversions
       type Element (<>) is limited private;
    package Object_Conversions is
       function To_Atom (Value : in Element) return Atom;
       function To_Object (Value : in Atom) return Element;
    end Object_Conversions;

    type S_Expression (<>) is tagged private; -- An Atom or a list of S_Expression.

    function Make (Item : in Atom) return S_Expression;

    function Is_Atom (Expression : in S_Expression) return Boolean;

    Not_An_Atom : exception;

    function To_Atom (Expression : in S_Expression) return Atom;
    -- Raises Not_An_Atom if not Is_Atom (Expression);

    Empty_List : constant S_Expression;

    Not_A_List : exception;

    function Append (Onto : in S_Expression; Value : in S_Expression) return 
S_Expression;
    -- Returns a list consisting of the exisiting list Onto with Value appended 
to it.
    -- Raises Not_A_List if Is_Atom (Onto);

    procedure Iterate
       (Over : in S_Expression; Process : not null access procedure (Expression 
: in S_Expression; Continue : in out Boolean) );
    -- Passes each element of Over to Process in turn, with Continue => True.
    -- Returns immediately if Process sets Continue to False; remaining elements 
will not be processed.
    -- Raises Not_A_List if Is_Atom (Over).
private -- S_Expressions
    Byte_Size : constant := 8;

    type Byte_Value is mod 2 ** Byte_Size;

    package Byte_Lists is new Ada.Containers.Vectors (Index_Type => Positive, 
Element_Type => Byte_Value);

    type Atom is record
       Value : Byte_Lists.Vector;
    end record;

    type Root is tagged null record;

    package Lists is new Ada.Containers.Indefinite_Vectors (Index_Type => 
Positive, Element_Type => Root'Class);

    type S_Expression (Is_Atom : Boolean) is new Root with record
       case Is_Atom is
       when False =>
          List : Lists.Vector;
       when True =>
          Value : Atom;
       end case;
    end record;

    Empty_List : constant S_Expression := (Is_Atom => False, List => 
Lists.Empty_Vector);
end S_Expressions;

with Ada.Unchecked_Conversion;

package body S_Expressions is
    function To_Atom (Value : in String) return Atom is
       Result : Atom;
    begin -- To_Atom
       All_Characters : for I in Value'range loop
          Result.Value.Append (New_Item => Character'Pos (Value (I) ) );
       end loop All_Characters;

       return Result;
    end To_Atom;

    function To_String (Value : in Atom) return String is
       Result : String (Value.Value.First_Index .. Value.Value.Last_Index);
    begin -- To_String
       All_Bytes : for I in Result'range loop
          Result (I) := Character'Val (Value.Value.Element (I) );
       end loop All_Bytes;

       return Result;
    end To_String;

    package body Object_Conversions is
       type Byte_List is array (Positive range <>) of Byte_Value;

       function To_Atom (Value : in Element) return Atom is
          Num_Bytes : constant Positive := (Value'Size + Byte_Size - 1) / Byte_Size;

          subtype Element_List is Byte_List (1 .. Num_Bytes);

          function Convert is new Ada.Unchecked_Conversion (Source => Element, 
Target => Element_List);

          Byte : Element_List renames Convert (Value);

          Result : Atom;
       begin -- To_Atom
          All_Bytes : for I in Byte'range loop
             Result.Value.Append (New_Item => Byte (I) );
          end loop All_Bytes;

          return Result;
       end To_Atom;

       function To_Object (Value : in Atom) return Element is
          subtype Element_List is Byte_List (Value.Value.First_Index .. 
Value.Value.Last_Index);

          function Convert is new Ada.Unchecked_Conversion (Source => 
Element_List, Target => Element);

          Byte : Element_List;
       begin -- To_Object
          All_Bytes : for I in Byte'range loop
             Byte (I) := Value.Value.Element (I);
          end loop All_Bytes;

          return Convert (Byte);
       end To_Object;
    end Object_Conversions;

    function Make (Item : in Atom) return S_Expression is
       -- null;
    begin -- Make
       return S_Expression'(Is_Atom => True, Value => Item);
    end Make;

    function Is_Atom (Expression : in S_Expression) return Boolean is
       -- null;
    begin -- Is_Atom
       return Expression.Is_Atom;
    end Is_Atom;

    function To_Atom (Expression : in S_Expression) return Atom is
       -- null;
    begin -- To_Atom
       if not Expression.Is_Atom then
          raise Not_An_Atom;
       end if;

       return Expression.Value;
    end To_Atom;

    function Append (Onto : in S_Expression; Value : in S_Expression) return 
S_Expression is
       Result : S_Expression (Is_Atom => False);
    begin -- Append
       if Onto.Is_Atom then
          raise Not_A_List;
       end if;

       Result.List := Onto.List;
       Result.List.Append (New_Item => Value);

       return Result;
    end Append;

    procedure Iterate
       (Over : in S_Expression; Process : not null access procedure (Expression 
: in S_Expression; Continue : in out Boolean) )
    is
       Continue : Boolean := True;
    begin -- Iterate
       if Over.Is_Atom then
          raise Not_A_List;
       end if;

       All_Expressions : for I in Over.List.First_Index .. Over.List.Last_Index loop
          Process (Expression => S_Expression (Over.List.Element (I) ), Continue 
=> Continue);

          exit All_Expressions when not Continue;
       end loop All_Expressions;
    end Iterate;
end S_Expressions;

I think this includes all necessary functionality to build and process 
S-expressions, though you might have some additional operations you might like 
to add. Reading it might prove instructional, whether you like this approach or not.

-- 
Jeff Carter
"I'm a lumberjack and I'm OK."
Monty Python's Flying Circus
54

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---



^ permalink raw reply	[relevance 5%]

* Re: S-expression I/O in Ada
  @ 2010-08-01 18:25  6% ` Jeffrey Carter
    2010-08-27 13:19  3% ` Natasha Kerensikova
  2 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2010-08-01 18:25 UTC (permalink / raw)


On 08/01/2010 05:17 AM, Natacha Kerensikova wrote:
>
> To describe briefly S-expressions, I consider them to be the simplest
> existing data organization beyond raw sequences of bits. They are
> basically lists of elements, each element being either a list or an
> atom, and atoms being raw sequences of bits.

You might very well be able to use something like:

package Byte_Lists is new Ada.Containers.Vectors (Index_Type => Positive, 
Element_Type => System.Storage_Elements.Storage_Element);

type Content_ID is (Atom, List);

type S_Expression;
type S_Expression_Ptr is access all S_Expression;

type S_Expression_Element (Content : Content_ID := Atom) is record
    case Content is
    when Atom =>
       Byte : Byte_Lists.Vector;
    when List =>
       Ptr : S_Expression_Ptr;
    end case;
end record;

package S_Expression_Lists is new Ada.Containers.Doubly_Linked_Lists 
(Element_Type => S_Expression_Element);

type S_Expression is new S_Expression_Lists.List;

If you can use unbounded strings as Brenta suggested, instead of an unbounded 
array of bytes (Storage_Element), then this would be even simpler.

-- 
Jeff Carter
"People called Romanes, they go the house?"
Monty Python's Life of Brian
79

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---



^ permalink raw reply	[relevance 6%]

* Re: Lambda expressions? LINQ?
  2009-09-19 14:35  5%           ` Brad Moore
@ 2009-09-19 16:38  0%             ` Martin
  0 siblings, 0 replies; 200+ results
From: Martin @ 2009-09-19 16:38 UTC (permalink / raw)


On Sep 19, 3:35 pm, Brad Moore <brad.mo...@shaw.ca> wrote:
> Martin wrote:
> > On Sep 19, 3:33 am, "Steve D" <nospam_steve...@comcast.net> wrote:
> > [snip]
> >> As Martin guessed it is one statement spread over a few lines.
>
> >>             string[] names = xDoc.Descendants("Layer0Message")
> >>                               .SelectMany(node =>
> >> node.Attribute("To").Value.Split(' ',',').Where( st => st.Length > 0 ))
> >>                                   .Distinct().OrderBy(n=>n).ToArray();
>
> >> Oh, and by the way.  LINQ isn't just for XML.  You can do queries on arrays,
>
>  >> lists, etc.  For example if you have an array of records you can do a
>  >> query to select all of the records with a field that has a particular
>  >> value. It's cool.
>
> >> I just wish my favoriate language had this feature.
>
> > Me too - although I can't see how it could be :-(
>
> I'm not sure I see why this couldn't be.
> At first glance, the code fragment looks a lot like Ada.
>
> If existing packages (such as XML/Ada see
> (http://libre.adacore.com/libre/tools/xmlada/) do not already
> have this capability, then why couldn't someone write such a package in
> Ada? I don't see the language being a barrier here.
> Ada.Containers.Vectors for example lets you query an array of records to
> select all the records with a field that has a particular value.
>
> What is missing?
>
> Brad

Well, perhaps you could using the dot notation as above but the real
value of LINQ to me is the sql like syntax that you can see in
examples, such as those on the MS site, e.g.

public void Linq11() {
    List products = GetProductList();

    var productInfos =
        from p in products
        select new {p.ProductName, p.Category, Price = p.UnitPrice};

    Console.WriteLine("Product Info:");
    foreach (var productInfo in productInfos) {
        Console.WriteLine("{0} is in the category {1} and costs {2}
per unit.", productInfo.ProductName, productInfo.Category,
productInfo.Price);
    }
}

Check that 'select new {' line...very SQL! Even to my Ada-eyes a 'dot
notation' version just isn't as readable.

Cheers
-- Martin



^ permalink raw reply	[relevance 0%]

* Re: Lambda expressions? LINQ?
  @ 2009-09-19 14:35  5%           ` Brad Moore
  2009-09-19 16:38  0%             ` Martin
  0 siblings, 1 reply; 200+ results
From: Brad Moore @ 2009-09-19 14:35 UTC (permalink / raw)


Martin wrote:
> On Sep 19, 3:33 am, "Steve D" <nospam_steve...@comcast.net> wrote:
> [snip]
>> As Martin guessed it is one statement spread over a few lines.
>>
>>             string[] names = xDoc.Descendants("Layer0Message")
>>                               .SelectMany(node =>
>> node.Attribute("To").Value.Split(' ',',').Where( st => st.Length > 0 ))
>>                                   .Distinct().OrderBy(n=>n).ToArray();
>>
>> Oh, and by the way.  LINQ isn't just for XML.  You can do queries on arrays,
 >> lists, etc.  For example if you have an array of records you can do a
 >> query to select all of the records with a field that has a particular
 >> value. It's cool.
>> I just wish my favoriate language had this feature.
> 
> Me too - although I can't see how it could be :-(

I'm not sure I see why this couldn't be.
At first glance, the code fragment looks a lot like Ada.

If existing packages (such as XML/Ada see 
(http://libre.adacore.com/libre/tools/xmlada/) do not already
have this capability, then why couldn't someone write such a package in 
Ada? I don't see the language being a barrier here.
Ada.Containers.Vectors for example lets you query an array of records to
select all the records with a field that has a particular value.

What is missing?

Brad



^ permalink raw reply	[relevance 5%]

* Re: Ada in Denmark and a Wiki article
  @ 2009-09-07 15:49  6%     ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2009-09-07 15:49 UTC (permalink / raw)


Thomas Løcke wrote on comp.lang.ada:
> Ludovic Brenta wrote:
> > your nice page about Vectors is relevant to users of Ada outside
> > Denmark and is written in English, so I think this page should be in
> > the Ada Programming wikibook.
>
> When we planned the new website, we did discuss whether a new wiki was
> necessary or if we should just link directly to, for example, the Ada
> Programming wikibook, but we decided on going with our own, as we wanted
> freedom to do whatever we liked, and we guessed (maybe wrongly) that
> such freedom would not be possible,

Yes, you guessed wrongly. Everyone is welcome to contribute to the Ada
Programming wikibook. The existing page about Vectors[1] is very short
and would benefit greatly from your work. Meanwhile, your page is
probably not the first place newbies would find when looking for
information whereas, even a few minutes ago, someone posted a question
right here on comp.lang.ada after reading the now well-known Wikibook.

[1] http://en.wikibooks.org/wiki/Ada_Programming/Libraries/Ada.Containers.Vectors

> if we were to intrude on an already active wiki.

You have two people's sympathy already. You're not an intruder. And
the Ada Programming wiki is never active enough. :)

> With our own wiki, we can write whatever we want, however we want. And
> if other people feel some of our content is good enough to be added to
> for example the Ada Programming wikibook, then they are more than
> welcome to grab the content in question and add it. Copy it, modify it,
> use it. All content on the ada-dk.org wiki is made available under the
> GFDL 1.3 license.

That's called "duplication of effort" and "maintenance nightmare". Ada
was designed to maximize reuse and minimize the maintenance burden.
Heed her advice :)

--
Ludovic Brenta.



^ permalink raw reply	[relevance 6%]

* Re: Ada in Denmark and a Wiki article
  2009-09-07 11:52  6% Ada in Denmark and a Wiki article Thomas Løcke
@ 2009-09-07 13:53  0% ` Ludovic Brenta
    0 siblings, 1 reply; 200+ results
From: Ludovic Brenta @ 2009-09-07 13:53 UTC (permalink / raw)


Thomas Løcke wrote on comp.lang.ada:
> The new website comes with a Wiki. It is our goal to add
> beginner-friendly articles to this Wiki, as time permits. The first
> article is online and can be found at http://wiki.ada-dk.org/index.php/Ada.Containers.Vectors

Nice but I think it would be better if the Ada in Denmark web site
would concentrate on subjects that are specifically Danish (and quite
possibly written in Danish, too; there is nothing wrong with that);
your nice page about Vectors is relevant to users of Ada outside
Denmark and is written in English, so I think this page should be in
the Ada Programming wikibook.

Anyway, you have my sympathy if that matters to you :)

--
Ludovic Brenta.



^ permalink raw reply	[relevance 0%]

* Ada in Denmark and a Wiki article
@ 2009-09-07 11:52  6% Thomas Løcke
  2009-09-07 13:53  0% ` Ludovic Brenta
  0 siblings, 1 reply; 200+ results
From: Thomas Løcke @ 2009-09-07 11:52 UTC (permalink / raw)


Hey all,

For the past few years, Ada in Denmark has been without a website. This 
is no longer the case, as http://ada-dk.org relaunched a few months ago. 
Hopefully we will be able to attract more danish Ada programmers, now 
that we're online again.

If you're a danish Ada programmer, please consider joining Ada in 
Denmark:  http://ada-dk.org/?page=join

We'd love to have more members.

The new website comes with a Wiki. It is our goal to add 
beginner-friendly articles to this Wiki, as time permits. The first 
article is online and can be found at 
http://wiki.ada-dk.org/index.php/Ada.Containers.Vectors

In case it isn't obvious from the above URL, this article is about the 
Ada.Containers.Vectors package. The goal of the article is to *show*, 
with actual code, beginners how the various procedures/functions in the 
Vectors package work.

If there are any glaring mistakes in the article, please let me know, 
and I'll fix them ASAP. Or you can just sign up, and add/remove/alter 
the page as you wish. It is a Wiki after all.  :o)

Please bear in mind, that the article is still being edited by someone 
with a much higher degree of proficiency in the english language (thanks 
Dwight!) than me. My first language, naturally, is danish, so there's 
bound to be quite a few errors in the text, as I struggle along with the 
english language. Hopefully Dwight will have most of the errors cleared 
away "soon".

-- 
Regards,
Thomas L�cke

Email: tl at ada-dk.org
Web: http:ada-dk.org
IRC nick: ThomasLocke



^ permalink raw reply	[relevance 6%]

* Re: C++0x and Threads - a poor relation to Ada's tasking model?
  @ 2009-08-12 15:00  5%       ` Maciej Sobczak
  0 siblings, 0 replies; 200+ results
From: Maciej Sobczak @ 2009-08-12 15:00 UTC (permalink / raw)


On 12 Sie, 07:29, stefan-lu...@see-the.signature wrote:

> This is easy, since "%s\n" is a constant.

Of course. And *static* analysis of keyword-based multitasking usage
patterns is also easy *only* if these patterns are in some way
constant (static).

Nothing prevents me from screwing up an instance of
Ada.Containers.Vectors.Vector, Ada.Text_IO.File_Type, or just about
anything else if I use it from multiple tasks without wrapping it in
the protected object.
(that's what I have done recently)

It is *exactly* the same problem - you can always make the analysis
difficult by moving from static to dynamic.
What does it prove?

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

Database Access Library for Ada: www.inspirel.com/soci-ada



^ permalink raw reply	[relevance 5%]

* Re: Allocation questions
  @ 2009-05-28 16:59  6% ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2009-05-28 16:59 UTC (permalink / raw)


Olivier Scalbert wrote:
> 
> Here is the code (As delay is a reserved word in Ada, I use Delay_T as I 
> found nothing better !):

Delay_Info
Delay_Data

> 1) Is there a way to avoid the dynamic array allocation, as I do not 
> know the Time_Value at compile time ?

You cannot avoid dynamic allocation. However, you can do the dynamic allocation 
on the stack (variable-sized record), or on the heap (explicit access values or 
an unbounded data structure such as Ada.Containers.Vectors).

An object allocated on the stack is likely to have a smaller maximum size than 
one allocated on the heap.

If you are going to use the heap, I would recommend using a data structure, as 
it will do the memory management for you. The memory management in 
Ada.Containers is more likely to be correct than something you write yourself, 
and to remain correct as you modify your code.

If you are going to use a variable-sized record, you should declare (sub)types 
that reflect the constraints implicit in the implementation. For example, there 
is a maximum usable value of type Time, since you have to be able to multiply 
any supplied value by the sampling rate. This also implies a maximum number of 
samples that may be handled at a time:

type Time_Base is new Float;

Sampling_Rate : constant := 44_100;

Max_Time : constant Time_Base := Time_Base'Last / Sampling_Rate;

subtype Time is Time_Base range 0.0 .. Max_Time;

Max_Samples : constant Positive :=
    Integer (Time'Truncation (Max_Time * Sampling_Rate) );

As this last declaration is likely to raise Constraint_Error, it's probably 
better to start with the maximum number of samples and work backward:

Max_Samples : constant := 30_000;
-- Arbitrary value; replace with something meaningful from the application.

Max_Time : constant Time_Base := Time_Base (Max_Samples) / Sampling_Rate;

subtype Sample_Index is Positive range 1 .. Max_Samples;

type Sample_List is array (Sample_Index range <>) of Sample;

package Sample_Lists is new Ada.Containers.Vectors
    (Index_Type => Sample_Index, Element_Type => Sample);

-- 
Jeff Carter
"What lazy lout left these wires all over the lawn?"
Poppy
98



^ permalink raw reply	[relevance 6%]

* Re: Vectors.Insert_Space bug?
  2009-05-20 20:59  7% Vectors.Insert_Space bug? Thomas Løcke
@ 2009-05-21  1:56  0% ` John B. Matthews
  0 siblings, 0 replies; 200+ results
From: John B. Matthews @ 2009-05-21  1:56 UTC (permalink / raw)


In article <4a146f41$0$90265$14726298@news.sunsite.dk>,
 Thomas Løcke <thomas.granvej6@gmail.com> wrote:

> I've stumbled on some weird behavior while trying to make use of the 
> Ada.Containers.Vectors.Insert_Space procedure. According to the RM, this 
> is what it should do:
> 
> "... Then Insert_Space slides the elements in the range Before .. 
> Last_Index (Container) up by Count positions, and then inserts empty 
> elements in the positions starting at Before."
> 
> But that is not at all what I'm seeing, as this small test-program will 
> show:
[...]
> The output from the Test program is:
> 
>   1 Item 1
>   2 Item 2
>   3 Item 3
>   4 Item 4
>   5 Item 5
>   6
>   7
>   8 Item 5
> 
> Which IMHO is wrong. There shouldn't be two "Item 5" elements. And it's 
> possible to make it even worse, by calling Insert_Space multiple times 
> with different Before and Count parameters.
> 
> It seems as if the element located at the Before index is copied and 
> inserted as the first new element, and only after that, does 
> Insert_Space actually start inserting empty elements.
> 
> I've tried to compile with two different compilers, and both exhibit 
> this odd behavior:
> 	GNATMAKE 4.2.3
> 	GNATMAKE  GPL 2008 (20080521)
> 
> I admit to just being a hobbyist, so this might just be me not "getting" 
> what the RM is trying to tell me, but I do think the text is fairly clear.
> 
> Any help would be greatly appreciated.

I get the same result with 4.3.4.

It looks like the old element 5 slid to position 8. The three empties 
are at positions 5, 6 and 7. Note that "Empty elements do not have a 
specified value." In particular, "Reading the value of an empty element 
by calling Element" is a bounded error, and "The implementation may 
treat the [empty] element as having any normal value...":

<http://www.adaic.com/standards/05rm/html/RM-A-18-2.html>

-- 
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>



^ permalink raw reply	[relevance 0%]

* Vectors.Insert_Space bug?
@ 2009-05-20 20:59  7% Thomas Løcke
  2009-05-21  1:56  0% ` John B. Matthews
  0 siblings, 1 reply; 200+ results
From: Thomas Løcke @ 2009-05-20 20:59 UTC (permalink / raw)


Hey all,

I've stumbled on some weird behavior while trying to make use of the 
Ada.Containers.Vectors.Insert_Space procedure. According to the RM, this 
is what it should do:

"... Then Insert_Space slides the elements in the range Before .. 
Last_Index (Container) up by Count positions, and then inserts empty 
elements in the positions starting at Before."

But that is not at all what I'm seeing, as this small test-program will 
show:

--  Pasted code start  --

with Ada.Text_IO.Unbounded_IO;
with Ada.Strings.Unbounded;      use Ada.Strings.Unbounded;
with Ada.Containers.Vectors;     use Ada.Containers;

procedure Test is
    package SUIO renames Ada.Text_IO.Unbounded_IO;
    package US_Container is new Vectors (Positive, Unbounded_String);
    Testing : US_Container.Vector;
begin
    Testing.Append (New_Item => To_Unbounded_String ("Item 1"));
    Testing.Append (New_Item => To_Unbounded_String ("Item 2"));
    Testing.Append (New_Item => To_Unbounded_String ("Item 3"));
    Testing.Append (New_Item => To_Unbounded_String ("Item 4"));
    Testing.Append (New_Item => To_Unbounded_String ("Item 5"));

    Testing.Insert_Space (Before => 5,
                       Count => 3);

    for i in 1 .. Testing.Length loop
       SUIO.Put_Line (i'Img & " " & Testing.Element (Integer (i)));
    end loop;
end Test;

--  Pasted code end  --

The output from the Test program is:

  1 Item 1
  2 Item 2
  3 Item 3
  4 Item 4
  5 Item 5
  6
  7
  8 Item 5

Which IMHO is wrong. There shouldn't be two "Item 5" elements. And it's 
possible to make it even worse, by calling Insert_Space multiple times 
with different Before and Count parameters.

It seems as if the element located at the Before index is copied and 
inserted as the first new element, and only after that, does 
Insert_Space actually start inserting empty elements.

I've tried to compile with two different compilers, and both exhibit 
this odd behavior:
	GNATMAKE 4.2.3
	GNATMAKE  GPL 2008 (20080521)

I admit to just being a hobbyist, so this might just be me not "getting" 
what the RM is trying to tell me, but I do think the text is fairly clear.

Any help would be greatly appreciated.

Regards,
Thomas L�cke



^ permalink raw reply	[relevance 7%]

* Re: Load an object from a file
    2009-04-03 13:07  4% ` Niklas Holsti
@ 2009-04-03 13:41  8% ` Thomas Løcke
  1 sibling, 0 replies; 200+ results
From: Thomas Løcke @ 2009-04-03 13:41 UTC (permalink / raw)


Olivier Scalbert wrote:
> But I do not know what is the best (Ada) way of representing the array 
> of info constant_pool as the size is only known at run time.(= 
> constant_pool_cout).
> Also how can I fill this array ?
> 
> Thanks to help me and have a nice day.

Hey Olivier,

I don't know if it's the "best" way, but I would use 
Ada.Containers.Vector in your case. Here's a small example:

-----
with Ada.Text_IO;               use Ada.Text_IO;
with Ada.Containers.Vectors;    use Ada.Containers;

procedure Vec is
    type CP_Info_Type is new String (1 .. 3);
    package Constant_Pool_Container is new Vectors (Natural, CP_Info_Type);
    Constant_Pool : Constant_Pool_Container.Vector;
    CP_Info : CP_Info_Type;
begin
    CP_Info := "Foo";
    Constant_Pool.Append (New_Item => CP_Info);

    CP_Info := "Bar";
    Constant_Pool.Append (New_Item => CP_Info);

    CP_Info := "42!";
    Constant_Pool.Append (New_Item => CP_Info);

    for i in 0 .. Constant_Pool.Last_Index loop
       Put_Line (String (Constant_Pool.Element (Index => i)));
    end loop;
end Vec;
-----

If all goes well, output should be:

    Foo
    Bar
    42!

You can read more about Ada.Containers.Vectors here: 
http://adaic.org/standards/05rm/html/RM-A-18-2.html

:o)
/Thomas



^ permalink raw reply	[relevance 8%]

* Re: Load an object from a file
  @ 2009-04-03 13:07  4% ` Niklas Holsti
  2009-04-03 13:41  8% ` Thomas Løcke
  1 sibling, 0 replies; 200+ results
From: Niklas Holsti @ 2009-04-03 13:07 UTC (permalink / raw)


Olivier Scalbert wrote:
> Hello everybody !
> 
> In my Ada self-study context, I was asking myself how can I create and 
> fill objects or records from a file.
> As an example, I have tried to represent a java class file format 
> structure and fill it with a .class java file.
> 
> The ClassFile structure is something like:
> 
>     ClassFile {
>         u4 magic;
>         u2 minor_version;
>         u2 major_version;
>         u2 constant_pool_count;
>         cp_info constant_pool[constant_pool_count-1];
>         u2 access_flags;
>         u2 this_class;
>         u2 super_class;
>         u2 interfaces_count;
>         u2 interfaces[interfaces_count];
>         u2 fields_count;
>         field_info fields[fields_count];
>         u2 methods_count;
>         method_info methods[methods_count];
>         u2 attributes_count;
>         attribute_info attributes[attributes_count];
>     }
> 
> 
> JVM Specs can be found there:
> http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html
> 
> I have no problem to represent and to fill from file, the first four 
> fields.
> But I do not know what is the best (Ada) way of representing the array 
> of info constant_pool as the size is only known at run time.(= 
> constant_pool_cout).

You could use suitable container structures, for example 
Ada.Containers.Vectors. That would hide the storage management from 
your problem space.

There are two more basic methods:

1. Make the size components discriminants of the record, not
    ordinary components:

    type Constant_Pool_T is array (Positive range <>) of cp_info;
    ... etc types for the other arrays.

    type Class_File_T (
       Constant_Pool_Count : u2;
       Interfaces_Count    : u2;
       Fields_Count        : u2;
       Attributes_Count    : u2)
    is record
       ...
       Constant_Pool : Constant_Pool_T (1 .. Constant_Pool_Count);
       ...
       Attributes : Attributes_T (1 .. Attributes_Count);
    end record;

    In this method, you must know the sizes of the arrays
    before you can create the Class_File_T object. This could
    be hard in your case -- I assume you must read the components
    from a file in the order given in the record type, so you
    would have to read all constant-pool items before reading
    interfaces_count, for example.

    In this method it is more convenient to index the
    arrays starting from 1, not 0, because you cannot do
    arithmetic on the discriminants to define the array
    bounds; the "-1" is forbidden here:

    type Class_File_T ( ... ) is record
       ...
       Constant_Pool :
          Constant_Pool_T (0 .. Constant_Pool_Count - 1);
       ...
    end record;

2. Use heap allocation and access types:

    type Constant_Pool_T is array Natural range <>) of cp_info;
    type Constant_Pool_Ref is access Constant_Pool_T;

    type Class_File_T is record
       ...
       Constant_Pool : Constant_Pool_Ref;
       ...
       Attributes : Attributes_Ref;
    end record;

    In this method, you can create the Class_File_T object
    before you know the array sizes. The components Constant_Pool
    etc. will initially be null. When you know the size, you
    can create arrays of the right size on the heap:

       CF.Constant_Pool :=
          new Constant_Pool_T (0 .. constant_pool_count - 1);

HTH,

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[relevance 4%]

* Re: Performance of element access in Vector
  2009-01-18 21:42  6% Performance of element access in Vector Maciej Sobczak
  2009-01-19  0:03  0% ` george.priv
@ 2009-01-19  3:23  0% ` george.priv
  1 sibling, 0 replies; 200+ results
From: george.priv @ 2009-01-19  3:23 UTC (permalink / raw)


On Jan 18, 4:42 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
> In a nearby thread I have asked about the performance of
> Update_Element in Vector.
> The question was related to using the same interface in smart pointers
> (and other containers/handlers).
>
> So I wrote a test:
>
> with Ada.Calendar.Formatting;
> with Ada.Containers.Vectors;
> with Ada.Text_IO;
>
> procedure A is
>
>    package Int_Vectors is new Ada.Containers.Vectors
>      (Index_Type => Positive, Element_Type => Integer);
>
>    V : Int_Vectors.Vector := Int_Vectors.To_Vector(0, 1_000_000);
>
>    procedure Increment (I : in out Integer) is
>    begin
>       I := I + 1;
>    end Increment;
>
>    Iterations : constant := 10_000;
>
>    Start : Ada.Calendar.Time;
>    Stop : Ada.Calendar.Time;
>
>    use type Ada.Calendar.Time;
>
>    procedure Test_1 is
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          for I in V.First_Index .. V.Last_Index loop
>             V.Replace_Element (I, V.Element (I) + 1);
>          end loop;
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("direct index             : " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_1;
>
>    procedure Test_2 is
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          for I in V.First_Index .. V.Last_Index loop
>             V.Update_Element (I, Increment'Access);
>          end loop;
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("Update_Element and index : " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_2;
>
>    procedure Test_3 is
>       C : Int_Vectors.Cursor;
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          C := V.First;
>          while Int_Vectors.Has_Element (C) loop
>             V.Replace_Element (C, Int_Vectors.Element (C) + 1);
>             Int_Vectors.Next (C);
>          end loop;
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("direct cursor            : " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_3;
>
>    procedure Test_4 is
>       C : Int_Vectors.Cursor;
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          C := V.First;
>          while Int_Vectors.Has_Element (C) loop
>             V.Update_Element (C, Increment'Access);
>             Int_Vectors.Next (C);
>          end loop;
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("Update_Element and cursor: " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_4;
>
>    procedure Test_5 is
>
>       procedure Increment (C : in Int_Vectors.Cursor) is
>       begin
>          V.Replace_Element (C, Int_Vectors.Element (C) + 1);
>       end Increment;
>
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          V.Iterate (Increment'Access);
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("Iterate                  : " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_5;
>
> begin
>    Test_1;
>    Test_2;
>    Test_3;
>    Test_4;
>    Test_5;
> end A;
>
> Each of the tests increments all vectors elements, using several
> element access methods.
> Here we go:
>
> ~/temp/ada $ gnatmake -O2 -gnatn -gnatN a
> gcc -c -O2 -gnatn -gnatN a.adb
> gnatbind -x a.ali
> gnatlink a.ali
> ~/temp/ada $ ./a
> direct index             : 00:00:23.34
> Update_Element and index : 00:02:17.20
> direct cursor            : 00:01:03.32
> Update_Element and cursor: 00:02:25.82
> Iterate                  : 00:01:48.67
> ~/temp/ada $
>
> The test shows that Update_Element is several time slower than
> accessing elements by index. Cursor also adds some overhead.
>
> A possible conclusion is that for small elements (simple numeric
> types, etc.) it makes sense to access elements by index, when they are
> copied from and into the container. For larger elements the benefit of
> accessing element in-place can be greater than the overhead of
> Update_Element.
>
> Just to stir the discussion a bit, a straightforward implementation of
> the same test in C++ (with the same base compiler and a single -O2
> option) runs in 13s with indexed access and in 9.5s with iterators -
> both are based on the use of references, which do not exist in Ada.
> Not very easy to neglect this difference.
>
> All comments are welcome.
>
> --
> Maciej Sobczak *www.msobczak.com*www.inspirel.com
>
> Database Access Library for Ada:www.inspirel.com/soci-ada

Very interesting.

It seems that compiler is unable to inline.  I've added extra test to
see what will be performance with raw array:

   Z : array (0 .. 1_000_000) of Integer := (others => 0);


   procedure Test_0 is
   begin
      Start := Ada.Calendar.Clock;

      for J in 1 .. Iterations loop
         for I in Z'range loop
            Z(I) := Z(I) + 1;
         end loop;
      end loop;


      Stop := Ada.Calendar.Clock;
      Ada.Text_IO.Put_Line
        ("raw array                : " &
           Ada.Calendar.Formatting.Image (Stop - Start, True));
   end Test_0;

Results came as:

raw array                : 00:00:09.82
direct index             : 00:00:23.02
Update_Element and index : 00:01:29.96
direct cursor            : 00:02:22.65
Update_Element and cursor: 00:03:36.51
Iterate                  : 00:02:13.03





^ permalink raw reply	[relevance 0%]

* Re: Performance of element access in Vector
  2009-01-18 21:42  6% Performance of element access in Vector Maciej Sobczak
@ 2009-01-19  0:03  0% ` george.priv
  2009-01-19  3:23  0% ` george.priv
  1 sibling, 0 replies; 200+ results
From: george.priv @ 2009-01-19  0:03 UTC (permalink / raw)


On Jan 18, 4:42 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
> In a nearby thread I have asked about the performance of
> Update_Element in Vector.
> The question was related to using the same interface in smart pointers
> (and other containers/handlers).
>
> So I wrote a test:
>
> with Ada.Calendar.Formatting;
> with Ada.Containers.Vectors;
> with Ada.Text_IO;
>
> procedure A is
>
>    package Int_Vectors is new Ada.Containers.Vectors
>      (Index_Type => Positive, Element_Type => Integer);
>
>    V : Int_Vectors.Vector := Int_Vectors.To_Vector(0, 1_000_000);
>
>    procedure Increment (I : in out Integer) is
>    begin
>       I := I + 1;
>    end Increment;
>
>    Iterations : constant := 10_000;
>
>    Start : Ada.Calendar.Time;
>    Stop : Ada.Calendar.Time;
>
>    use type Ada.Calendar.Time;
>
>    procedure Test_1 is
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          for I in V.First_Index .. V.Last_Index loop
>             V.Replace_Element (I, V.Element (I) + 1);
>          end loop;
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("direct index             : " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_1;
>
>    procedure Test_2 is
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          for I in V.First_Index .. V.Last_Index loop
>             V.Update_Element (I, Increment'Access);
>          end loop;
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("Update_Element and index : " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_2;
>
>    procedure Test_3 is
>       C : Int_Vectors.Cursor;
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          C := V.First;
>          while Int_Vectors.Has_Element (C) loop
>             V.Replace_Element (C, Int_Vectors.Element (C) + 1);
>             Int_Vectors.Next (C);
>          end loop;
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("direct cursor            : " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_3;
>
>    procedure Test_4 is
>       C : Int_Vectors.Cursor;
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          C := V.First;
>          while Int_Vectors.Has_Element (C) loop
>             V.Update_Element (C, Increment'Access);
>             Int_Vectors.Next (C);
>          end loop;
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("Update_Element and cursor: " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_4;
>
>    procedure Test_5 is
>
>       procedure Increment (C : in Int_Vectors.Cursor) is
>       begin
>          V.Replace_Element (C, Int_Vectors.Element (C) + 1);
>       end Increment;
>
>    begin
>       Start := Ada.Calendar.Clock;
>
>       for J in 1 .. Iterations loop
>          V.Iterate (Increment'Access);
>       end loop;
>
>       Stop := Ada.Calendar.Clock;
>       Ada.Text_IO.Put_Line
>         ("Iterate                  : " &
>            Ada.Calendar.Formatting.Image (Stop - Start, True));
>    end Test_5;
>
> begin
>    Test_1;
>    Test_2;
>    Test_3;
>    Test_4;
>    Test_5;
> end A;
>
> Each of the tests increments all vectors elements, using several
> element access methods.
> Here we go:
>
> ~/temp/ada $ gnatmake -O2 -gnatn -gnatN a
> gcc -c -O2 -gnatn -gnatN a.adb
> gnatbind -x a.ali
> gnatlink a.ali
> ~/temp/ada $ ./a
> direct index             : 00:00:23.34
> Update_Element and index : 00:02:17.20
> direct cursor            : 00:01:03.32
> Update_Element and cursor: 00:02:25.82
> Iterate                  : 00:01:48.67
> ~/temp/ada $
>
> The test shows that Update_Element is several time slower than
> accessing elements by index. Cursor also adds some overhead.
>
> A possible conclusion is that for small elements (simple numeric
> types, etc.) it makes sense to access elements by index, when they are
> copied from and into the container. For larger elements the benefit of
> accessing element in-place can be greater than the overhead of
> Update_Element.
>
> Just to stir the discussion a bit, a straightforward implementation of
> the same test in C++ (with the same base compiler and a single -O2
> option) runs in 13s with indexed access and in 9.5s with iterators -
> both are based on the use of references, which do not exist in Ada.
> Not very easy to neglect this difference.
>
> All comments are welcome.
>
> --
> Maciej Sobczak *www.msobczak.com*www.inspirel.com
>
> Database Access Library for Ada:www.inspirel.com/soci-ada




^ permalink raw reply	[relevance 0%]

* Performance of element access in Vector
@ 2009-01-18 21:42  6% Maciej Sobczak
  2009-01-19  0:03  0% ` george.priv
  2009-01-19  3:23  0% ` george.priv
  0 siblings, 2 replies; 200+ results
From: Maciej Sobczak @ 2009-01-18 21:42 UTC (permalink / raw)


In a nearby thread I have asked about the performance of
Update_Element in Vector.
The question was related to using the same interface in smart pointers
(and other containers/handlers).

So I wrote a test:

with Ada.Calendar.Formatting;
with Ada.Containers.Vectors;
with Ada.Text_IO;

procedure A is

   package Int_Vectors is new Ada.Containers.Vectors
     (Index_Type => Positive, Element_Type => Integer);

   V : Int_Vectors.Vector := Int_Vectors.To_Vector(0, 1_000_000);

   procedure Increment (I : in out Integer) is
   begin
      I := I + 1;
   end Increment;

   Iterations : constant := 10_000;

   Start : Ada.Calendar.Time;
   Stop : Ada.Calendar.Time;

   use type Ada.Calendar.Time;

   procedure Test_1 is
   begin
      Start := Ada.Calendar.Clock;

      for J in 1 .. Iterations loop
         for I in V.First_Index .. V.Last_Index loop
            V.Replace_Element (I, V.Element (I) + 1);
         end loop;
      end loop;

      Stop := Ada.Calendar.Clock;
      Ada.Text_IO.Put_Line
        ("direct index             : " &
           Ada.Calendar.Formatting.Image (Stop - Start, True));
   end Test_1;

   procedure Test_2 is
   begin
      Start := Ada.Calendar.Clock;

      for J in 1 .. Iterations loop
         for I in V.First_Index .. V.Last_Index loop
            V.Update_Element (I, Increment'Access);
         end loop;
      end loop;

      Stop := Ada.Calendar.Clock;
      Ada.Text_IO.Put_Line
        ("Update_Element and index : " &
           Ada.Calendar.Formatting.Image (Stop - Start, True));
   end Test_2;

   procedure Test_3 is
      C : Int_Vectors.Cursor;
   begin
      Start := Ada.Calendar.Clock;

      for J in 1 .. Iterations loop
         C := V.First;
         while Int_Vectors.Has_Element (C) loop
            V.Replace_Element (C, Int_Vectors.Element (C) + 1);
            Int_Vectors.Next (C);
         end loop;
      end loop;

      Stop := Ada.Calendar.Clock;
      Ada.Text_IO.Put_Line
        ("direct cursor            : " &
           Ada.Calendar.Formatting.Image (Stop - Start, True));
   end Test_3;

   procedure Test_4 is
      C : Int_Vectors.Cursor;
   begin
      Start := Ada.Calendar.Clock;

      for J in 1 .. Iterations loop
         C := V.First;
         while Int_Vectors.Has_Element (C) loop
            V.Update_Element (C, Increment'Access);
            Int_Vectors.Next (C);
         end loop;
      end loop;

      Stop := Ada.Calendar.Clock;
      Ada.Text_IO.Put_Line
        ("Update_Element and cursor: " &
           Ada.Calendar.Formatting.Image (Stop - Start, True));
   end Test_4;

   procedure Test_5 is

      procedure Increment (C : in Int_Vectors.Cursor) is
      begin
         V.Replace_Element (C, Int_Vectors.Element (C) + 1);
      end Increment;

   begin
      Start := Ada.Calendar.Clock;

      for J in 1 .. Iterations loop
         V.Iterate (Increment'Access);
      end loop;

      Stop := Ada.Calendar.Clock;
      Ada.Text_IO.Put_Line
        ("Iterate                  : " &
           Ada.Calendar.Formatting.Image (Stop - Start, True));
   end Test_5;

begin
   Test_1;
   Test_2;
   Test_3;
   Test_4;
   Test_5;
end A;

Each of the tests increments all vectors elements, using several
element access methods.
Here we go:

~/temp/ada $ gnatmake -O2 -gnatn -gnatN a
gcc -c -O2 -gnatn -gnatN a.adb
gnatbind -x a.ali
gnatlink a.ali
~/temp/ada $ ./a
direct index             : 00:00:23.34
Update_Element and index : 00:02:17.20
direct cursor            : 00:01:03.32
Update_Element and cursor: 00:02:25.82
Iterate                  : 00:01:48.67
~/temp/ada $

The test shows that Update_Element is several time slower than
accessing elements by index. Cursor also adds some overhead.

A possible conclusion is that for small elements (simple numeric
types, etc.) it makes sense to access elements by index, when they are
copied from and into the container. For larger elements the benefit of
accessing element in-place can be greater than the overhead of
Update_Element.

Just to stir the discussion a bit, a straightforward implementation of
the same test in C++ (with the same base compiler and a single -O2
option) runs in 13s with indexed access and in 9.5s with iterators -
both are based on the use of references, which do not exist in Ada.
Not very easy to neglect this difference.

All comments are welcome.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

Database Access Library for Ada: www.inspirel.com/soci-ada



^ permalink raw reply	[relevance 6%]

* Vector of Vectors.
@ 2009-01-15  0:32  7% Peter C. Chapin
  0 siblings, 0 replies; 200+ results
From: Peter C. Chapin @ 2009-01-15  0:32 UTC (permalink / raw)


I'm having a bit of trouble manipulating an element of a vector of
vectors. I'm using GNAT GPL 2008. Here is a small program to illustrate
the issue:

with Ada.Containers.Vectors;

procedure Check is
   package Integer_Vectors is
      new Ada.Containers.Vectors
         (Index_Type   => Natural,
          Element_Type => Integer);

   package Nested_Vectors is
      new Ada.Containers.Vectors
         (Index_Type   => Natural,
          Element_Type => Integer_Vectors.Vector,
          "="          => Integer_Vectors."=");

   IV : Integer_Vectors.Vector;
   NV : Nested_Vectors.Vector;
begin
   IV.Append(42);
   NV.Append(IV);
   NV.Element(0).Append(43);  -- Compile error here.
end Check;

The error message is, "Actual for Container must be a variable." I
understand what this means. The problem is that I'm trying to use an
expression as an argument for an 'in out' parameter. What I'm having
trouble figuring out is how to work around this. I tried using 'renames'
to give a simple name to NV.Element(0) but that didn't fool the compiler
(no surprise). I also tried playing around with anonymous access types
but I couldn't figure out how to declare the Element_Type of package
Nested_Vectors to be aliased. I'm not sure if it would have worked in
any case.

Surely there must be a straight forward way to do this!

Peter



^ permalink raw reply	[relevance 7%]

* Re: Array of Strings
  @ 2008-09-23 14:47  5%         ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2008-09-23 14:47 UTC (permalink / raw)


mockturtle wrote:
> On Sep 23, 4:07 pm, jedivaughn <jedivaugh...@gmail.com> wrote:
> > If I wanted to make a package that made the array generic how would I
> > go about doing this. this is what I have which isn't working.
> >
> >     generic
> >
> >     type Element_Type is (<>);
> >     type range1 is (<>);
> >
> >    package list is
> >         type letters is private;
> >
> >         private
> >         type letters is array (range1) of Element_Type;
> >
> > end list;
> >
> > and then in the main program I want
> >
> >  subtype range2 is integer range 1..25;
> >  subtype str_length is string (1..25);
> >
> >  package List1 is new List(Element_Type => str_length, range1 =>
> > range2 );
> >
> > when I try to compile the main program I get "expect discrete type in
> > instantiation of "Element_Type""
> >
> > what am I doing wrong?
> >
>
> According to RM 12.5.2 "type Element_Type is (<>);" means that
> Element_Type
> is a discrete type.  I guess that you want something like
> "type Element_Type is private;" (I did not check)

That's correct.

To the OP: out of curiosity, why don't you use Ada.Containers.Vectors?
Even if you have good reason not to use this package, you will benefit
from reading its spec as a source of inspiration (aka "best
practices").

Also see http://en.wikibooks.org/wiki/Ada_Programming/Generics

--
Ludovic Brenta.



^ permalink raw reply	[relevance 5%]

* Re: Using Ada.Containers.Vector and Limited Private types
    2008-07-11 22:06  0%       ` Jeffrey R. Carter
@ 2008-07-12  7:53  0%       ` Dmitry A. Kazakov
  1 sibling, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2008-07-12  7:53 UTC (permalink / raw)


On Thu, 10 Jul 2008 15:59:30 -0700 (PDT), Gene wrote:
 
> procedure List_By_Date is
> 
>    type String_Ptr_Type is access String;
>    type File_Info_Type is
>       record
>          Modification_Time : Time;
>          Simple_Name : String_Ptr_Type; -- Freed with storage pool!
>       end record;
> 
>    package File_Info_Vectors is
>      new Ada.Containers.Vectors (Positive, File_Info_Type);

I am using a different design in such cases, which are a kind of cached
data store with sorted items.

I would make a descriptor type containing all data of an item:

   type File_Info (Length : Natural) is record
      Modification_Time : Time;
      Simple_Name : String (1..Length);
      ...
   end record;

File_Info can be allocated in an arena or mark-and-release pool. That is no
matter. Then comparison operations are defined on the pointers rather than
the descriptors:

   type File_Info_By_Date is access all File_Info;
   function "<" (Left, Right : File_Info_By_Date) return Boolean;

   type File_Info_By_Name is access all File_Info;
   function "<" (Left, Right : File_Info_By_Name) return Boolean;

   type File_Info_By_Size is access all File_Info;
   function "<" (Left, Right : File_Info_By_Size) return Boolean;

etc.

Then I would create ordered sets of File_Info_By_Date, File_Info_By_Name
and so on. All this I put into a controlled object which takes care about
inserting and removing items. Indexes of pointers are kept sorted. This is
exactly the design I used for a persistency layer.

(I don't use Ada.Containers, but I think this approach should work with
them too.)

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



^ permalink raw reply	[relevance 0%]

* Re: Using Ada.Containers.Vector and Limited Private types
  2008-07-11 22:06  0%       ` Jeffrey R. Carter
@ 2008-07-12  2:45  0%         ` Gene
  0 siblings, 0 replies; 200+ results
From: Gene @ 2008-07-12  2:45 UTC (permalink / raw)


On Jul 11, 6:06 pm, "Jeffrey R. Carter"
<spam.jrcarter....@spam.acm.org> wrote:
> Gene wrote:
>
> > But as Dmitry pointed out, what I wrote has some portability risk.  To
> > avoid this, just copy the bits you need into your own (non-limited)
> > data structure.
>
> > with Ada.Text_IO;            use Ada.Text_IO;
> > with Ada.Integer_Text_IO;    use Ada.Integer_Text_IO;
> > with Ada.Containers.Vectors;
> > with Ada.Directories;        use Ada.Directories;
> > with Ada.Calendar;           use Ada.Calendar; -- for comparing  date/
> > times
>
> > procedure List_By_Date is
>
> >    type String_Ptr_Type is access String;
> >    type File_Info_Type is
> >       record
> >          Modification_Time : Time;
> >          Simple_Name : String_Ptr_Type; -- Freed with storage pool!
>
> I would recommend using Ada.Strings.Unbounded.Unbounded_String with its
> automatic and tested memory management over implementing new and untested memory
> allocation and management yourself.
>
> --
> Jeff Carter
> "Well, a gala day is enough for me. I don't think
> I can handle any more."
> Duck Soup
> 93- Hide quoted text -
>
> - Show quoted text -

Right.  I initially did it with UBS and changed it. Unbounded_String,
at least in the GNAT implementation, is a super heavyweight.  In this
case, you call Simple_Name to get a string and then convert it to an
unbounded string.  In Ada 95 you'd have to convert back to a simple
String for printing; fortunately that's fixed in 2005.  Nonetheless
the syntax and the compiled code are both unsatisfying.  Barnes seems
to agree:

... conversion between bounded and unbounded strings and the raw type
String is required rather a lot and is both ugly and inefficient.

I do not find that relying on a simple new' and storage pool for
release to be a very intimidating form of memory management.



^ permalink raw reply	[relevance 0%]

* Re: Using Ada.Containers.Vector and Limited Private types
  @ 2008-07-11 22:06  0%       ` Jeffrey R. Carter
  2008-07-12  2:45  0%         ` Gene
  2008-07-12  7:53  0%       ` Dmitry A. Kazakov
  1 sibling, 1 reply; 200+ results
From: Jeffrey R. Carter @ 2008-07-11 22:06 UTC (permalink / raw)


Gene wrote:
> 
> But as Dmitry pointed out, what I wrote has some portability risk.  To
> avoid this, just copy the bits you need into your own (non-limited)
> data structure.
> 
> with Ada.Text_IO;            use Ada.Text_IO;
> with Ada.Integer_Text_IO;    use Ada.Integer_Text_IO;
> with Ada.Containers.Vectors;
> with Ada.Directories;        use Ada.Directories;
> with Ada.Calendar;           use Ada.Calendar; -- for comparing  date/
> times
> 
> procedure List_By_Date is
> 
>    type String_Ptr_Type is access String;
>    type File_Info_Type is
>       record
>          Modification_Time : Time;
>          Simple_Name : String_Ptr_Type; -- Freed with storage pool!

I would recommend using Ada.Strings.Unbounded.Unbounded_String with its 
automatic and tested memory management over implementing new and untested memory 
allocation and management yourself.

-- 
Jeff Carter
"Well, a gala day is enough for me. I don't think
I can handle any more."
Duck Soup
93



^ permalink raw reply	[relevance 0%]

Results 1-200 of ~400   | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2008-07-05 11:53     Using Ada.Containers.Vector and Limited Private types Dale Stanbrough
2008-07-06 18:09     ` Gene
2008-07-10  0:16       ` Dale Stanbrough
2008-07-10 22:59         ` Gene
2008-07-11 22:06  0%       ` Jeffrey R. Carter
2008-07-12  2:45  0%         ` Gene
2008-07-12  7:53  0%       ` Dmitry A. Kazakov
2008-09-13 14:18     Array of Strings jedivaughn
2008-09-15 14:54     ` Adam Beneschan
2008-09-16 23:56       ` jedivaughn
2008-09-23 14:07         ` jedivaughn
2008-09-23 14:30           ` mockturtle
2008-09-23 14:47  5%         ` Ludovic Brenta
2009-01-15  0:32  7% Vector of Vectors Peter C. Chapin
2009-01-18 21:42  6% Performance of element access in Vector Maciej Sobczak
2009-01-19  0:03  0% ` george.priv
2009-01-19  3:23  0% ` george.priv
2009-04-03 12:01     Load an object from a file Olivier Scalbert
2009-04-03 13:07  4% ` Niklas Holsti
2009-04-03 13:41  8% ` Thomas Løcke
2009-05-20 20:59  7% Vectors.Insert_Space bug? Thomas Løcke
2009-05-21  1:56  0% ` John B. Matthews
2009-05-28  9:46     Allocation questions Olivier Scalbert
2009-05-28 16:59  6% ` Jeffrey R. Carter
2009-08-11 15:30     C++0x and Threads - a poor relation to Ada's tasking model? John McCabe
2009-08-11 23:53     ` jimmaureenrogers
2009-08-12  7:26       ` Maciej Sobczak
2009-08-12  5:29         ` stefan-lucks
2009-08-12 15:00  5%       ` Maciej Sobczak
2009-09-07 11:52  6% Ada in Denmark and a Wiki article Thomas Løcke
2009-09-07 13:53  0% ` Ludovic Brenta
2009-09-07 14:27       ` 
2009-09-07 15:49  6%     ` Ludovic Brenta
2009-09-16  2:23     Lambda expressions? LINQ? Steve D
2009-09-16 10:46     ` Jeffrey R. Carter
2009-09-18  1:59       ` Steve D
2009-09-18  5:23         ` sjw
2009-09-19  2:33           ` Steve D
2009-09-19  6:50             ` Martin
2009-09-19 14:35  5%           ` Brad Moore
2009-09-19 16:38  0%             ` Martin
2010-08-01 12:17     S-expression I/O in Ada Natacha Kerensikova
2010-08-01 18:25  6% ` Jeffrey Carter
2010-08-17 17:01     ` Natasha Kerensikova
2010-08-17 19:00  5%   ` Jeffrey Carter
2010-08-18 10:49  0%     ` Natasha Kerensikova
2010-08-27 13:19  3% ` Natasha Kerensikova
2010-10-29  2:27     Do people who use Ada also use ocaml or F#? Chad  R. Meiners
2010-10-29  7:53     ` Dmitry A. Kazakov
2010-10-30 12:18       ` Florian Weimer
2010-10-30 12:59         ` Dmitry A. Kazakov
2010-10-30 19:12           ` Yannick Duchêne (Hibou57)
2010-10-30 19:37             ` Dmitry A. Kazakov
2010-10-31 21:46               ` Shark8
2010-11-01  9:32                 ` Dmitry A. Kazakov
2010-11-05 12:46                   ` Robert A Duff
2010-11-06 17:22                     ` Stephen Leake
2010-11-06 20:56  4%                   ` Robert A Duff
2010-11-27  9:47     Callback in Ada Georg Maubach
2010-11-27 10:22  4% ` Ludovic Brenta
2010-11-28  3:21     Properties Shark8
2010-11-30  1:49     ` Properties Randy Brukardt
2010-11-30 16:58       ` Properties Charmed Snark
2010-11-30 17:22         ` Properties Dmitry A. Kazakov
2010-11-30 20:27           ` Properties Warren
2010-12-01  8:39             ` Properties Dmitry A. Kazakov
2010-12-01 15:21               ` Properties Warren
2010-12-01 15:59                 ` Properties Dmitry A. Kazakov
2010-12-03  5:53  4%               ` Properties Shark8
2010-12-03  9:05  0%                 ` Properties Dmitry A. Kazakov
2010-12-03 19:52  3%                   ` Properties Shark8
2010-12-03 21:14  0%                     ` Properties Randy Brukardt
2011-09-17 16:30     discriminant questions ytomino
2011-09-18 10:54     ` ytomino
2011-09-18 11:35       ` Dmitry A. Kazakov
2011-09-18 16:46         ` Robert A Duff
2011-09-18 18:01           ` Dmitry A. Kazakov
2011-09-18 19:20             ` Maciej Sobczak
2011-09-19  7:39               ` Dmitry A. Kazakov
2011-09-19 20:00                 ` Maciej Sobczak
2011-09-20  7:33                   ` Dmitry A. Kazakov
2011-09-20 15:45                     ` Maciej Sobczak
2011-09-20 16:48                       ` Dmitry A. Kazakov
2011-09-20 20:19                         ` Maciej Sobczak
2011-09-21  7:48                           ` Dmitry A. Kazakov
2011-09-21 20:51                             ` Maciej Sobczak
2011-09-22  8:07                               ` Dmitry A. Kazakov
2011-09-22 20:57                                 ` Maciej Sobczak
2011-09-23  7:59                                   ` Dmitry A. Kazakov
2011-09-23 10:57  6%                                 ` Georg Bauhaus
2011-12-10 20:43     Interrupts handling in ADA Ada @ BRL
2011-12-10 22:27  7% ` Simon Wright
2011-12-13 12:47  0%   ` Ada BRL
2011-12-13 15:07  0%     ` Simon Wright
2011-12-13 15:23  0%       ` Ada BRL
2011-12-18 12:34     String_Holder ? Natasha Kerensikova
2011-12-19 11:12  7% ` Martin
2012-01-21 18:19 13% Efficiency and overhead: Ada.Containers.Vectors.vector versus array type Ada BRL
2012-01-21 18:40  6% ` Simon Wright
2012-01-21 19:11  5% ` Jeffrey Carter
2012-01-22 15:05  7%   ` Ada BRL
2012-05-05 12:55  6% Problem in "X (1).Re := X (1).Re + 1" ytomino
2012-05-07 15:37  0% ` Adam Beneschan
2012-05-07 18:53  5%   ` ytomino
2012-05-07 21:28  0%     ` Adam Beneschan
2012-05-08  1:14           ` Randy Brukardt
2012-05-08 17:14             ` Adam Beneschan
2012-05-08 22:29               ` Randy Brukardt
2012-05-09  8:41  6%             ` ytomino
2012-05-10  0:52  0%               ` Randy Brukardt
2012-05-17 20:20     Vector (container) initialization: the schizophrenic ampersand Marius Amado-Alves
2012-05-17 23:33     ` Adam Beneschan
2012-05-18  6:51       ` Marius Amado-Alves
2012-05-18 13:31         ` Robert A Duff
2012-05-19  9:03           ` Marius Amado-Alves
2012-05-19 16:15             ` Robert A Duff
2012-05-21 16:02               ` Adam Beneschan
2012-05-21 17:04                 ` Robert A Duff
2012-05-21 17:57  5%               ` Adam Beneschan
2012-06-04 18:49     Distributed Systems Annex, data sharing between programs Adam Beneschan
2012-06-05  7:36     ` Maciej Sobczak
2012-06-05 16:02       ` Adam Beneschan
2012-06-06  7:39         ` Maciej Sobczak
2012-06-06 10:09           ` Niklas Holsti
2012-06-06 11:40             ` Maciej Sobczak
2012-06-06 20:02               ` Niklas Holsti
2012-06-07 10:37                 ` Maciej Sobczak
2012-06-08  2:11                   ` Shark8
2012-06-08  6:31  5%                 ` Pascal Obry
2012-06-22  9:08  3% begin/end reducing memory consumption? Anonymous
2012-10-08  9:03  6% API design considerations - variable-length array in record type Maciej Sobczak
2012-10-08 11:13  0% ` Simon Wright
2012-10-08 11:29  0% ` Egil Høvik
2012-10-09  3:10  0% ` Stephen Leake
2012-10-31 16:26  6% Copy vector in Ada katolsster
2012-10-31 16:37  6% ` Jeffrey Carter
2012-11-12 22:09     Ada202X : Adding functors Martin
2012-11-15  0:20     ` sbelmont700
2012-11-15  7:12       ` Martin
2012-11-15 12:31  7%     ` Georg Bauhaus
2012-11-15 12:46  0%       ` Martin
2012-11-27 21:02     IBM 437 encoded String to UTF-16 Wide_String gautier_niouzes
2012-11-27 23:41     ` Vadim Godunko
2012-11-28  8:34       ` briot.emmanuel
2012-11-28  8:52         ` Dmitry A. Kazakov
2012-11-28  9:43           ` Georg Bauhaus
2012-11-28  9:58             ` Dmitry A. Kazakov
2012-11-28 11:31               ` Georg Bauhaus
2012-11-28 13:36                 ` Dmitry A. Kazakov
2012-11-28 13:47                   ` Georg Bauhaus
2012-11-28 14:23                     ` Dmitry A. Kazakov
2012-11-28 17:35  6%                   ` Georg Bauhaus
2012-12-31  0:16     asynchronous task communication Charles Hixson
2012-12-31 12:09     ` Georg Bauhaus
2012-12-31 18:52       ` Charles Hixson
2012-12-31 21:09         ` Niklas Holsti
2013-01-01  3:51           ` Charles Hixson
2013-01-01 12:32             ` Jeffrey Carter
2013-01-01 18:21               ` Charles Hixson
2013-01-01 18:54                 ` Robert A Duff
2013-01-02  7:36                   ` Charles Hixson
2013-01-02  9:55                     ` Dmitry A. Kazakov
2013-01-02 19:02                       ` Charles Hixson
2013-01-02 20:35                         ` Dmitry A. Kazakov
2013-01-03  0:20                           ` Charles Hixson
2013-01-03 22:27                             ` Randy Brukardt
2013-01-05  5:18  6%                           ` Charles Hixson
2013-01-05  8:48  0%                             ` Niklas Holsti
2013-01-06 22:55  0%                               ` Charles Hixson
2013-01-07  6:07  7%                                 ` Shark8
2013-01-08  2:41  0%                             ` Randy Brukardt
2013-01-04  4:27  5% On Style: Any opinions on *not* capitalising the first letter of verbs in a procedure name ? Rod Kay
2013-01-04 16:31  0% ` Adam Beneschan
2013-01-04 18:32  0% ` Simon Wright
2013-01-05 14:11  0%   ` Stephen Leake
2013-01-05 14:06  0% ` Stephen Leake
2013-02-06  0:54     chopping Ada source that have preprocessor symbols in them Georg Bauhaus
2013-02-06  5:29     ` codeallergy
2013-02-06 12:00  7%   ` Georg Bauhaus
2013-03-11 19:42     Is this expected behavior or not Anh Vo
2013-03-15 21:46     ` Robert A Duff
2013-03-16  5:52       ` Shark8
2013-03-16  7:41         ` Dmitry A. Kazakov
2013-03-16 16:55           ` Shark8
2013-03-16 17:36             ` Dmitry A. Kazakov
2013-03-16 21:51               ` Shark8
2013-03-17  9:36                 ` Dmitry A. Kazakov
2013-03-18 23:13                   ` Randy Brukardt
2013-03-19  9:12                     ` Dmitry A. Kazakov
2013-03-19 21:19                       ` Randy Brukardt
2013-03-20 11:21                         ` Dmitry A. Kazakov
2013-03-20 23:57                           ` Randy Brukardt
2013-03-21 10:30                             ` Dmitry A. Kazakov
2013-03-21 23:27                               ` Randy Brukardt
2013-03-22 16:07                                 ` Dmitry A. Kazakov
2013-03-23  2:33                                   ` Randy Brukardt
2013-03-23  9:53                                     ` Dmitry A. Kazakov
2013-03-25 22:58                                       ` Randy Brukardt
2013-03-26 10:52                                         ` Dmitry A. Kazakov
2013-03-26 21:31                                           ` Randy Brukardt
2013-03-27  9:37  3%                                         ` Dmitry A. Kazakov
2013-03-27 19:42  0%                                           ` Randy Brukardt
2013-03-28 13:50  0%                                             ` Dmitry A. Kazakov
2013-03-28 21:55  0%                                               ` Randy Brukardt
2013-03-29 12:26                                                     ` Dmitry A. Kazakov
2013-03-30  0:49                                                       ` Randy Brukardt
2013-03-30  9:20                                                         ` Dmitry A. Kazakov
2013-04-02  0:40                                                           ` Randy Brukardt
2013-04-02  8:44                                                             ` Dmitry A. Kazakov
2013-04-02 21:54  2%                                                           ` Randy Brukardt
2013-07-01  9:02     Thick bindings to a C library and gnattest: suggestions? ziotom78
2013-07-01 17:16  4% ` Jeffrey Carter
2013-07-19 17:46     orthogonal inheritance and extension aggregates Felix Krause
2013-07-19 19:05  7% ` Dmitry A. Kazakov
2013-08-02 16:39  5% How can I declare a collection of an interface? Graham Stark
2013-08-02 16:53  0% ` Eryndlia Mavourneen
2013-08-02 18:28  6% ` Adam Beneschan
2013-08-09 20:35     Generics and Child Packages sbelmont700
2013-08-11 15:49     ` sbelmont700
2013-08-11 16:51  8%   ` Robert A Duff
2013-11-24  7:20     How To Pass Large Object Arguments FritzVonBraun
2013-11-25 16:53  6% ` adambeneschan
2014-01-10 22:00     'Protected' abstract subprograms sbelmont700
2014-01-10 22:30     ` Randy Brukardt
2014-01-11 16:12       ` sbelmont700
2014-01-14  3:45         ` Randy Brukardt
2014-01-14  9:05           ` Dmitry A. Kazakov
2014-01-15  0:36             ` Randy Brukardt
2014-01-15  9:17               ` Dmitry A. Kazakov
2014-01-15 14:11                 ` Robert A Duff
2014-01-15 15:40                   ` adambeneschan
2014-01-15 21:21                     ` Robert A Duff
2014-01-15 23:10                       ` Randy Brukardt
2014-01-16  0:51  5%                     ` Robert A Duff
2014-01-23 18:53     Binary and XML serialization of types hanslad
2014-01-23 19:15     ` adambeneschan
2014-01-23 19:17       ` adambeneschan
2014-01-23 19:58         ` hanslad
2014-01-24  8:44           ` Georg Bauhaus
2014-01-24 17:13  5%         ` Simon Wright
2014-01-23 22:44  5%   ` Simon Wright
2014-01-23 23:43  0%     ` adambeneschan
2014-01-24  0:58  0%       ` Randy Brukardt
2014-02-13 23:57     Something I don't understand Laurent
2014-02-14  0:18     ` adambeneschan
2014-02-15 15:27       ` Laurent
2014-02-15 19:10         ` Laurent
2014-02-16  1:39           ` Robert A Duff
2014-02-16  9:08             ` Text_IO, was: " Simon Clubley
2014-02-16 16:17               ` Robert A Duff
2014-02-17 12:52                 ` Simon Clubley
2014-02-17 16:59                   ` Niklas Holsti
2014-02-17 17:17                     ` Dmitry A. Kazakov
2014-02-17 17:42                       ` Niklas Holsti
2014-02-17 19:55                         ` Dmitry A. Kazakov
2014-02-18  7:14                           ` Niklas Holsti
2014-02-18  8:40                             ` Dmitry A. Kazakov
2014-02-18  9:00                               ` Niklas Holsti
2014-02-18  9:31                                 ` Dmitry A. Kazakov
2014-02-19  8:36                                   ` Niklas Holsti
2014-02-19  9:40                                     ` Dmitry A. Kazakov
2014-02-19 13:20                                       ` Niklas Holsti
2014-02-19 14:13                                         ` Dmitry A. Kazakov
2014-02-19 21:45  3%                                       ` Niklas Holsti
2014-02-20  9:52  3%                                         ` Dmitry A. Kazakov
2014-05-02  8:42     Safety of unprotected concurrent operations on constant objects Natasha Kerensikova
2014-05-03 13:43     ` sbelmont700
2014-05-03 20:54       ` Natasha Kerensikova
2014-05-03 21:40         ` Simon Wright
2014-05-04  0:28           ` Jeffrey Carter
2014-05-04  7:46             ` Natasha Kerensikova
2014-05-04 15:18               ` sbelmont700
2014-05-04 15:57                 ` Natasha Kerensikova
2014-05-05 19:04                   ` Brad Moore
2014-05-05 21:23                     ` Brad Moore
2014-05-04 21:44                       ` Shark8
2014-05-05  8:39                         ` Simon Wright
2014-05-05 15:11  4%                       ` Brad Moore
2014-05-05 16:36  0%                         ` Dmitry A. Kazakov
2014-05-06  6:00  5%                           ` Brad Moore
2014-05-06  8:11  0%                             ` Dmitry A. Kazakov
2014-05-08  4:12  0%                               ` Brad Moore
2014-05-08  8:20  0%                                 ` Dmitry A. Kazakov
2014-05-09 13:14  0%                                   ` Brad Moore
2014-05-08 22:37  7% <> syntax in generic formal_package_actual_part Georg Bauhaus
2014-05-08 23:20  5% ` Adam Beneschan
2014-05-09 13:05  0%   ` G.B.
2014-06-03  1:37     a new language, designed for safety ! Nasser M. Abbasi
2014-06-09 10:03     ` Pascal Obry
2014-06-10  9:36       ` Stephen Leake
2014-06-11  8:27         ` Maciej Sobczak
2014-06-11 19:39           ` Peter Chapin
2014-06-11 19:52             ` Luke A. Guest
2014-06-12  1:39               ` Peter Chapin
2014-06-12  2:46                 ` Dan'l Miller
2014-06-12 11:24                   ` Peter Chapin
2014-06-12 14:48                     ` björn lundin
2014-06-12 22:12                       ` Simon Clubley
2014-06-13  8:36                         ` Dmitry A. Kazakov
2014-06-13 20:57                           ` Robert A Duff
2014-06-16 16:39                             ` Randy Brukardt
2014-06-16 21:53                               ` Robert A Duff
2014-06-16 23:02                                 ` Jeffrey Carter
2014-06-16 23:42  8%                               ` Robert A Duff
2014-06-16  8:03  7% Lotto simulation 2 montgrimpulo
2014-08-13  2:07     Pointer to instance of indefinite array? NiGHTS
2014-08-13  2:29     ` Shark8
2014-08-13  3:06       ` NiGHTS
2014-08-13  4:28         ` Jeffrey Carter
2014-08-13 16:06           ` NiGHTS
2014-08-13 17:43  6%         ` Jeffrey Carter
2014-08-28 17:56  7% 'for cursor in container.first loop' bug? Stephen Leake
2014-08-28 19:56  0% ` Randy Brukardt
2014-09-07 10:33     bug or feature Charly
2014-09-08  9:43  6% ` Simon Wright
2014-09-23  0:43     Trying to understand Ada.Finalization.Controlled assignment mechanics Jeremiah
2014-09-23  1:17     ` Jeffrey Carter
2014-09-23 16:08       ` Jeremiah
2014-09-23 19:19  5%     ` Robert A Duff
2014-09-23 21:59  0%       ` Jeremiah
2015-02-27 19:26  6% "STORAGE_ERROR : s-intman.adb:139 explicit raise" from record containing a queue from Ada.Containers.Bounded_Synchronized_Queues in Gnat Ada 2014 jocpaine
2015-04-19 20:27  8% Deleting elements from a Vector Simon Wright
2015-04-19 21:07  0% ` Jeffrey Carter
2015-04-19 21:12  0% ` Niklas Holsti
2015-07-27 14:28     Running a preprocessor from GPS? EGarrulo
2015-07-27 20:26     ` Randy Brukardt
2015-07-28 11:36       ` EGarrulo
2015-07-28 21:12         ` Randy Brukardt
2015-07-28 22:11           ` EGarrulo
2015-07-29 20:32             ` Randy Brukardt
2015-07-29 22:32               ` EGarrulo
2015-07-29 23:51                 ` Jeffrey R. Carter
2015-07-30  0:10                   ` EGarrulo
2015-07-30  6:01                     ` Niklas Holsti
2015-07-30  7:33                       ` Björn Lundin
2015-07-30  8:03                         ` EGarrulo
2015-07-30  8:08                           ` Jacob Sparre Andersen
2015-07-30  8:37                             ` EGarrulo
2015-07-30 19:29                               ` Jeffrey R. Carter
2015-07-30 20:53                                 ` EGarrulo
2015-07-31  7:53  6%                               ` gautier_niouzes
2015-07-31 21:13     container of a container Hedley Rainnie
2015-07-31 21:48  8% ` Niklas Holsti
2015-08-04  2:23     Indefinite Containers of Indefinite Private Types Jeffrey R. Carter
2015-08-04  5:40     ` Niklas Holsti
2015-08-04 18:56       ` Jeffrey R. Carter
2015-08-07 20:13         ` Bob Duff
2015-08-07 20:45  6%       ` Jeffrey R. Carter
2015-09-08 15:10  4% working with diferent instances of the same generic interface Aitor Alcrudo Sangros
2015-09-09  6:38     ` Jacob Sparre Andersen
2015-09-09 11:08  5%   ` Aitor Alcrudo Sangros
2015-11-10 22:00     Bounded String question Serge Robyns
2015-11-11  0:48     ` Bob Duff
2015-11-11 10:52       ` Serge Robyns
2015-11-11 15:41  5%     ` Bob Duff
2016-03-20 11:15  6% Confused about class-wide types Mart van de Wege
2016-03-20 12:29  0% ` Dmitry A. Kazakov
2016-03-20 12:46  0% ` Simon Wright
2016-03-20 13:18  0% ` Shark8
2016-03-20 13:56  0%   ` Mart van de Wege
2016-03-21 21:54  0%   ` Randy Brukardt
2016-04-20 23:59  4% Non_Primitive Operations and Object.Operation Resolution Jeffrey R. Carter
2016-04-21 20:28  0% ` Randy Brukardt
2016-07-31  0:31     Is it possible to make a possibly self-referential type using containers? Shark8
2016-07-31  5:36  5% ` Jeffrey R. Carter
2016-09-28 13:25  5% Limited type in generic package causes double free or corruption onox
2016-09-28 16:20     ` Jeffrey R. Carter
2016-09-28 18:41  5%   ` onox
2016-09-28 17:27  0% ` Anh Vo
2016-10-05  7:28  7% Ada 2005 problem using Iterate Roger
2016-10-05  8:15  0% ` Alejandro R. Mosteo
2016-11-28 23:49     Ada 2012 Constraints (WRT an Ada IR) Shark8
2016-12-11 11:21     ` G.B.
2016-12-11 12:28       ` Dmitry A. Kazakov
2016-12-11 13:31         ` G.B.
2016-12-11 15:40           ` Dmitry A. Kazakov
2016-12-11 20:51             ` G.B.
2016-12-12  8:27               ` Dmitry A. Kazakov
2016-12-12 15:31                 ` G.B.
2016-12-12 17:39                   ` Dmitry A. Kazakov
2016-12-12 18:55                     ` G.B.
2016-12-12 20:53                       ` Dmitry A. Kazakov
2016-12-13  7:15                         ` G.B.
2016-12-13  8:27                           ` Dmitry A. Kazakov
2016-12-13 10:39                             ` G.B.
2016-12-13 11:19                               ` Dmitry A. Kazakov
2016-12-13 16:59                                 ` G.B.
2016-12-13 21:11                                   ` Dmitry A. Kazakov
2016-12-13 22:13                                     ` Shark8
2016-12-14  8:42                                       ` Dmitry A. Kazakov
2016-12-14 19:23                                         ` Shark8
2016-12-14 20:04                                           ` Dmitry A. Kazakov
2016-12-14 21:46                                             ` Shark8
2016-12-15  8:41                                               ` Dmitry A. Kazakov
2016-12-15 10:31                                                 ` G.B.
2016-12-15 13:17                                                   ` Dmitry A. Kazakov
2016-12-15 19:50                                                     ` G.B.
2016-12-16 10:04                                                       ` Dmitry A. Kazakov
2016-12-16 11:48                                                         ` G.B.
2016-12-16 12:56                                                           ` Stefan.Lucks
2016-12-16 19:59  5%                                                         ` Randy Brukardt
2017-03-09 13:45     Getting the index for an element in mutually referencing containers Mart van de Wege
     [not found]     ` <ly7f3xedp4.fsf@pushface.org>
     [not found]       ` <86k27xpikd.fsf@gaheris.avalon.lan>
     [not found]         ` <lywpbxc9my.fsf@pushface.org>
     [not found]           ` <86wpbxneuz.fsf@gaheris.avalon.lan>
     [not found]             ` <o9vcbp$t0t$1@franka.jacob-sparre.dk>
2017-03-11  8:40               ` Simon Wright
2017-03-11  8:58                 ` Dmitry A. Kazakov
2017-03-11 11:21                   ` Simon Wright
2017-03-11 14:18                     ` Dmitry A. Kazakov
2017-03-11 20:05                       ` Simon Wright
2017-03-11 20:52                         ` Dmitry A. Kazakov
2017-03-11 21:46                           ` Simon Wright
2017-03-12  8:20                             ` Dmitry A. Kazakov
2017-03-12 11:30                               ` Simon Wright
2017-03-12 11:55                                 ` Dmitry A. Kazakov
2017-03-12 16:44  7%                               ` Simon Wright
2017-03-12 17:42  0%                                 ` Dmitry A. Kazakov
2017-03-13 23:25  0%                                   ` Simon Wright
2017-03-14  8:25  5%                                     ` Dmitry A. Kazakov
2017-06-26 16:39 13% Ada.Containers.Vectors hnptz
2017-06-26 18:06  7% ` Ada.Containers.Vectors Per Sandberg
2017-06-27  6:15  7% ` Ada.Containers.Vectors G.B.
2017-10-28 11:10 11% Is Ada.Containers.Vectors.Reference_Type a constrained view? Stephen Leake
2017-11-15  0:38  5% ` Randy Brukardt
2018-02-23  2:36  7% Possible GNAT bug, but wanted to see if it was a violtion of the RM Jere
2018-04-15 21:48     How to get Ada to “cross the chasm”? Dan'l Miller
2018-05-04 16:13     ` guyclaude.burger
2018-05-04 19:05  5%   ` Jere
2018-05-29 19:41     Memory pools John Perry
2018-05-31 19:28  5% ` gorgelo
2018-05-31 19:33  5% ` gorgelo
2018-06-08  5:52  5% GNATCOLL JSON Parsing eduardsapotski
2018-06-08  9:35  0% ` Björn Lundin
2018-06-08 12:00  0% ` Per Sandberg
2018-12-22  5:37  5% Сreate attributes eduardsapotski
2018-12-22 19:13  0% ` Brad Moore
2019-01-02 15:48  3% class wide iterable (and indexable) George Shapovalov
2019-01-02 17:39  4% ` Simon Wright
2019-01-02 18:11  6%   ` George Shapovalov
2019-01-03  8:52  0%     ` Simon Wright
2019-01-03 22:56  0%     ` Randy Brukardt
2019-01-04  0:00           ` George Shapovalov
2019-01-04  8:43             ` Dmitry A. Kazakov
2019-01-04 12:20               ` George Shapovalov
2019-01-05 23:29                 ` Jere
2019-01-05 23:50                   ` Jere
2019-01-06  9:34  5%                 ` George Shapovalov
2019-01-05  9:21               ` Randy Brukardt
2019-01-05 10:07                 ` Dmitry A. Kazakov
2019-01-05 18:17  4%               ` George Shapovalov
2019-01-26 22:11  3% ` George Shapovalov
2019-01-25  9:43  4% Why forbid local generic instantiations? joakimds
2019-03-17 20:43  7% How to access Vector.Index_Type? jakub.dabek
2019-03-17 21:25  0% ` Simon Wright
2019-03-18  4:17  5% ` gautier_niouzes
2019-03-18  5:27  0% ` J-P. Rosen
2019-03-18  8:31  0%   ` Dmitry A. Kazakov
2019-03-18 19:35  0% ` Jeffrey R. Carter
2019-10-08 15:46  6% Funny (so to say...) interaction of "not null" and Vectors? mockturtle
2019-11-22 13:26  4% yes another gnat bug (inherited tagged type as record field is too much for gnat??) gerrshapovalov
2020-02-20 12:24  7% Different aliasing rules for containers? Martin B. B.
2020-02-20 13:36  0% ` joakimds
2020-02-20 13:47  0%   ` Martin B. B.
2020-04-03 22:48     Proposal: Auto-allocation of Indefinite Objects Stephen Davies
2020-07-27  7:47     ` Yannick Moy
2020-07-27 17:48       ` Brian Drummond
2020-07-27 20:31  7%     ` Jeffrey R. Carter
2020-06-16 11:31     How can I get this data into the .data section of the binary? Luke A. Guest
2020-06-16 14:14     ` Niklas Holsti
2020-06-16 14:25       ` Dmitry A. Kazakov
2020-06-16 14:42         ` Luke A. Guest
2020-06-16 15:21           ` Dmitry A. Kazakov
2020-06-16 15:43             ` Luke A. Guest
2020-06-16 16:11  5%           ` Dmitry A. Kazakov
2021-01-05 11:04     Lower bounds of Strings Stephen Davies
2021-01-06  3:08     ` Randy Brukardt
2021-01-06  9:13       ` Dmitry A. Kazakov
2021-01-07  0:17  6%     ` Randy Brukardt
2021-01-07  9:57  0%       ` Dmitry A. Kazakov
2021-01-07 22:03             ` Randy Brukardt
2021-01-08 17:23               ` Shark8
2021-01-08 20:19                 ` Dmitry A. Kazakov
2021-01-09  2:18                   ` Randy Brukardt
2021-01-09 10:53  5%                 ` Dmitry A. Kazakov
2021-02-03 17:47     specifying only 'First of an index in an array Mehdi Saada
2021-02-03 19:29  6% ` Jeffrey R. Carter
2021-04-17 21:45     Unchecked_Deallocation with tagged types DrPi
2021-04-18  8:21     ` Dmitry A. Kazakov
2021-04-18  8:46       ` Gautier write-only address
2021-04-18  9:09         ` Jeffrey R. Carter
2021-04-18 10:20           ` J-P. Rosen
2021-04-18 10:34             ` Dmitry A. Kazakov
2021-04-18 15:14               ` J-P. Rosen
2021-04-18 15:23                 ` Gautier write-only address
2021-04-20 18:53                   ` Randy Brukardt
2021-04-20 20:32                     ` Jeffrey R. Carter
2021-04-20 21:10                       ` Niklas Holsti
2021-04-24  0:49                         ` Randy Brukardt
2022-04-18  1:51  6%                       ` Thomas
2022-04-30  8:57  7% Question on in/out parameters reinert
2022-09-14 12:36  6% Non-standard functions in GNAT's Ada.Containers packages? G.B.
2022-09-14 16:04     ` Egil H H
2022-09-15  7:13       ` G.B.
2022-09-15 14:26         ` Marius Amado-Alves
2022-09-15 15:03           ` Niklas Holsti
2022-09-15 17:11             ` Marius Amado-Alves
2022-09-15 17:22               ` Dmitry A. Kazakov
2022-09-16 16:03                 ` Marius Amado-Alves
2022-09-16 16:30                   ` Marius Amado-Alves
2022-09-16 17:08  8%                 ` Jere
2022-09-26  6:54  7% Compiler error (2) ? reinert
2022-09-26  8:34  0% ` J-P. Rosen
2022-09-26  8:47  7%   ` reinert
2022-09-26  9:59  0%     ` reinert
2023-01-22 21:34     Real_Arrays on heap with overloaded operators and clean syntax Jim Paloander
2023-01-24 19:47  5% ` Gautier write-only address
2023-02-14  8:49 14% Use Ada.Containers.Vectors Generic_Sorting or Ada.Containers.Ordered_Sets ? reinert
2023-02-14  9:35  8% ` Jeffrey R.Carter
2023-02-14 10:46  8%   ` reinert
2023-02-14 18:48  8%     ` G.B.
2023-03-15 10:05  8% ` Marius Amado-Alves
2023-03-15 14:24  8% ` Brad Moore
2023-03-19  6:17  6% Is this a compiler bug ? Rod Kay
2023-04-17 14:20     Hi guys! I've been inactive for a long time but now started to develop a hobby application. I found a strange behaviour with gdb. Locally renaming a function S in order to shorten the source code visits cygwin.S during execution. thie is very awkwae Petter
2023-04-17 15:05     ` Niklas Holsti
2023-04-17 15:19       ` Simon Wright
2023-04-17 19:39         ` Chris Townley
2023-04-18 11:18  4%       ` Hi guys! I've been inactive for a long time but now started to develop a hobby application. I found a strange behaviour with gdb. Locally renaming a function S in order to shorten the source code visits cygwin.S during execution. thie is very awk Petter
2023-07-14 19:17  8% Formal Package Compiler Differences Jeffrey R.Carter
2023-07-14 19:27  0% ` Jeffrey R.Carter
2023-09-04  9:19     project euler 26 CSYH (QAQ)
2023-09-04 11:06     ` Niklas Holsti
2023-09-04 12:39       ` Dmitry A. Kazakov
2023-09-04 16:01         ` Ben Bacarisse
2023-09-04 19:20           ` Dmitry A. Kazakov
2023-09-04 20:18             ` Ben Bacarisse
2023-09-04 21:00               ` Dmitry A. Kazakov
2023-09-04 23:16                 ` Ben Bacarisse
2023-09-05  7:23                   ` Dmitry A. Kazakov
2023-09-05 15:18                     ` Ben Bacarisse
2023-09-05 17:08                       ` Dmitry A. Kazakov
2023-09-06  1:10                         ` Ben Bacarisse
2023-09-06  7:06                           ` Dmitry A. Kazakov
2023-09-06 15:16                             ` Ben Bacarisse
2023-09-06 15:54                               ` Dmitry A. Kazakov
2023-09-06 23:32                                 ` Ben Bacarisse
2023-09-07  9:02  4%                               ` Dmitry A. Kazakov
2023-09-08  1:32  0%                                 ` Ben Bacarisse
2023-09-08  7:23  0%                                   ` Dmitry A. Kazakov
2023-09-09  0:25  0%                                     ` Ben Bacarisse
2023-09-14 14:02  7% Aggregate with derived types Blady
2023-09-14 15:31  0% ` Jeffrey R.Carter
2023-09-14 20:00  0%   ` Blady

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