comp.lang.ada
 help / color / mirror / Atom feed
* Adding "()" operator to Ada 200X
@ 2003-06-02 16:35 Frank J. Lhota
  2003-06-02 23:42 ` Matthew Heaney
  2003-06-03  2:56 ` Fionn mac Cuimhaill
  0 siblings, 2 replies; 21+ messages in thread
From: Frank J. Lhota @ 2003-06-02 16:35 UTC (permalink / raw)


There appears to be wide agreement that Ada 200X should include some sort of
standard container library like Charles and PragMark. This library will
probably include generic packages for creating and operating with dynamic
lists and maps. One can view these kinds of collections as generalized
arrays, and as such, it would be nice to use array notation for accessing a
member of one of these collections. In other words, one should be able to
define the "()" operator for array-like types, as follows:

    function "()" ( Source : in Array_Like_Type;
                    Index  : in Index_Type )
       return Component_Type;

For example, if the object Roster is a list of objects of type Player_Type,
it would be quite desirable to be able to access the second player in Roster
as

    Roster(2)

For that matter, we could use the "()" operator to improve some existing Ada
packages. The Ada.Strings.Bounded and Ada.Strings.Unbounded packages define
the types Bounded_String and Unbounded_String that are enhanced versions of
the String type. If Item is of type Bounded_String / Unbounded_String, we
now access the third character of Item using the expression

    Element( Item, 3 )

Again, why not use the same notation that we would use if Item were declared
as Standard.String (assuming that Item'First = 1 ), i.e.

    Item(3)

If Ada 200X had an "()" operator, we could add the following declaration to
Ada.Strings.Unbounded

    function "()" (Source : in Unbounded_String;
                   Index  : in Positive)
       return Character renames Element;

With this declaration, we could use either "Element( Item, 3 )" or "Item(3)"
to get the third element of Item.

Of course, an array component can also be assigned a value, as in

    Item(3) := 'A':

For that reason, we may also want to add an "():=" operator that is used to
update a component of an array-like object, e.g.

    procedure "():=" ( Source : in out Array_Like_Type;
                       Index  : in     Index_Type;
                       Value  : in     Component_Type );

Again, we could enhance packages such as Ada.Strings.Bounded and
Ada.Strings.Unbounded by declaring a "():=" operator that could be used in
place of the Replace_Element procedures.

I cannot help but think that this would be of tremendous help with whatever
standard container library is added to Ada 200X.





^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-02 16:35 Adding "()" operator to Ada 200X Frank J. Lhota
@ 2003-06-02 23:42 ` Matthew Heaney
  2003-06-03 14:59   ` Frank J. Lhota
  2003-06-03 19:52   ` Francisco Javier Loma Daza
  2003-06-03  2:56 ` Fionn mac Cuimhaill
  1 sibling, 2 replies; 21+ messages in thread
From: Matthew Heaney @ 2003-06-02 23:42 UTC (permalink / raw)


"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> wrote in message news:<V0LCa.32473$ca5.11277@nwrdny02.gnilink.net>...
> There appears to be wide agreement that Ada 200X should include some sort of
> standard container library like Charles and PragMark. This library will
> probably include generic packages for creating and operating with dynamic
> lists and maps. One can view these kinds of collections as generalized
> arrays, and as such, it would be nice to use array notation for accessing a
> member of one of these collections. 
>
[snip]
> I cannot help but think that this would be of tremendous help with whatever
> standard container library is added to Ada 200X.

But all you've done is change the syntax.  None of your suggestions
allow you to do more than is already provided by the library.

To get a constant view of an element object, then all you have to do
is:

procedure Op (I : Iterator_Type) is
   E : ET := Element (I);
begin

To get an element object reference, you have to use an intermediate
access type.  To query do this:

procedure Op (I : Iterator_Type) is
   X : ET := To_Access (I).all;
begin

To modify do this:

procedure Op (I : Iterator_Type) is
begin
   To_Access (I).all := Y;

If you prefer, you can rename the element object.

procedure Op (I : Iterator_Type) is
   E : ET renames To_Access (I).all;
begin
   X := E;  --query
   E := Y;  --modify
end;

Alternatively, if you don't want to mess around with access types,
then you can use Replace_Element instead:

  Replace_Element (I, E);

If this is a set or a map, you can always unconditionally modify an
element using Insert:

  Insert (Set, E);
  --sort of like Set (Get_Key (E)) := E;

  Insert (Map, Key, E);
  --sort of like Map (Key) := E;

If you're going to make a change in the syntax of the language, then
it has be because it allows you to do something you can't do already. 
For example, there's no way to declare an access subtype right now
that means "all the access values except null."  A useful language
change would be to allow the declaration:

  type Element_Access_Base is access all Element_Type;

  subtype Element_Access is Element_Access_Base range not null;



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-02 16:35 Adding "()" operator to Ada 200X Frank J. Lhota
  2003-06-02 23:42 ` Matthew Heaney
@ 2003-06-03  2:56 ` Fionn mac Cuimhaill
  2003-06-03 14:02   ` Matthew Heaney
  2003-06-03 16:23   ` Mário Amado Alves
  1 sibling, 2 replies; 21+ messages in thread
From: Fionn mac Cuimhaill @ 2003-06-03  2:56 UTC (permalink / raw)


On Mon, 02 Jun 2003 16:35:01 GMT, "Frank J. Lhota"
<NOSPAM.lhota.adarose@verizon.net> wrote:

>There appears to be wide agreement that Ada 200X should include some sort of
>standard container library like Charles and PragMark. This library will
>probably include generic packages for creating and operating with dynamic
>lists and maps. One can view these kinds of collections as generalized
>arrays, and as such, it would be nice to use array notation for accessing a
>member of one of these collections. In other words, one should be able to
>define the "()" operator for array-like types, as follows:
>
>    function "()" ( Source : in Array_Like_Type;
>                    Index  : in Index_Type )
>       return Component_Type;
>
>

 To go along with this, a way to define a slice of of an
Array_Like_Type would be nice.





^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-03  2:56 ` Fionn mac Cuimhaill
@ 2003-06-03 14:02   ` Matthew Heaney
  2003-06-03 16:23   ` Mário Amado Alves
  1 sibling, 0 replies; 21+ messages in thread
From: Matthew Heaney @ 2003-06-03 14:02 UTC (permalink / raw)


Fionn mac Cuimhaill <invisible@hiding.from.spam> wrote in message news:<s53odv46kst9rb73a8tsuqmgft6d7ap105@4ax.com>...
> On Mon, 02 Jun 2003 16:35:01 GMT, "Frank J. Lhota"
> <NOSPAM.lhota.adarose@verizon.net> wrote:
> 
>  To go along with this, a way to define a slice of of an
> Array_Like_Type would be nice.

But you already can do that using iterators, e.g. 

  declare
     I, J : Iterator_Type;
  begin
     Equal_Range (Multimap, Key, I, J);
     --...
  end;

Here the range [I, J) designates the contiguous range of items having
key value Key.

You can use Find and Generic_Find to generalize this to elements
(instead of just keys), and to other kinds of containers such as a
List.

Once you have the iterator pair that designates the range, then you
can iterate over the range:

  while I /= J loop
    declare
       E : Element_Type renames To_Access (I).all;
    begin
       --...
    end;

    I := Succ (I);
  end loop;

You could also use a passive iterator.  For example, if you wanted to
copy a range of items (kind of like what a traditional slice does),
then you do something like:

   declare
      Another_List : List_Subtype;

      procedure Process (I : Iterator_Type) is
         E : constant Element_Type := Element (I);
         --or E : Element_Type renames To_Access (I).all;
      begin
         Push_Back (Another_List, E);
      end;

      procedure Iterate is
         new Generic_Select_Elements (Process);
   begin
      Iterate (I, J);

      --now Another_List has a copy of the elements 
      --from List in the range [I, J)
   end;



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-02 23:42 ` Matthew Heaney
@ 2003-06-03 14:59   ` Frank J. Lhota
  2003-06-03 15:09     ` Frank J. Lhota
                       ` (2 more replies)
  2003-06-03 19:52   ` Francisco Javier Loma Daza
  1 sibling, 3 replies; 21+ messages in thread
From: Frank J. Lhota @ 2003-06-03 14:59 UTC (permalink / raw)


"Matthew Heaney" <mheaney@on2.com> wrote in message
news:1ec946d1.0306021542.58714996@posting.google.com...
> But all you've done is change the syntax.  None of your suggestions
> allow you to do more than is already provided by the library.

But isn't the same thing true of all operators? Instead of defining "+" for
my types, I could define a function named Sum. It would have the same
functionality as the "+", it would just read differently.

OTOH, how an expression reads is very important! One of Ada's strengths is
its readability, and I would consider

    D := B * B - 4 * A * C;

to be more readable than

    D := Difference( Product( B, B ), Product( Product( 4, A ), C ) );

Part of why the former expression is clearer is that it uses the standard
arithmetic notation that one uses for numeric types. Thus, even if A, B, C
and D are not a numberic type (they could be matrices, for example), we
understand the author's intentions here.

From the very beginning, Ada has allowed programmers to define operators
such as "+", "*", "and", etc. for user defined types, so that the user types
can use the same notation as the predefined types. By analogy, why not do
the same for a user type that is analgous to an array? Isn't

    B( I ) := A( P( I ) ) + C( I );

clearer than

    Replace_Element( B, I, Element( A, Element( P, I ) ) + Element( C,
I ) );

> If you're going to make a change in the syntax of the language, then
> it has be because it allows you to do something you can't do already.
> For example, there's no way to declare an access subtype right now
> that means "all the access values except null."  A useful language
> change would be to allow the declaration:
>
>   type Element_Access_Base is access all Element_Type;
>
>   subtype Element_Access is Element_Access_Base range not null;

This is an interesting idea, and we should probably pursue it further in
another. Constraint checking has always been tremendously helpful. There is
one potential (but not insurmountable) problem with this proposal: in the
absence of explicit initializations, an access variable is initialized to
null.





^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-03 14:59   ` Frank J. Lhota
@ 2003-06-03 15:09     ` Frank J. Lhota
  2003-06-03 16:04     ` Martin Krischik
  2003-06-03 20:24     ` Randy Brukardt
  2 siblings, 0 replies; 21+ messages in thread
From: Frank J. Lhota @ 2003-06-03 15:09 UTC (permalink / raw)


"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> wrote in message
news:AJ2Da.34247$ca5.13684@nwrdny02.gnilink.net...
> This is an interesting idea, and we should probably pursue it further in
> another. Constraint ...

Whoops! I meant to say "... and we should probably pursue it further in
another thread".





^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-03 14:59   ` Frank J. Lhota
  2003-06-03 15:09     ` Frank J. Lhota
@ 2003-06-03 16:04     ` Martin Krischik
  2003-06-04 17:28       ` Matthew Heaney
  2003-06-03 20:24     ` Randy Brukardt
  2 siblings, 1 reply; 21+ messages in thread
From: Martin Krischik @ 2003-06-03 16:04 UTC (permalink / raw)


Frank J. Lhota wrote:

> But isn't the same thing true of all operators? Instead of defining "+"
> for my types, I could define a function named Sum. It would have the same
> functionality as the "+", it would just read differently.

I agree with your point and put my vote in favour of the O.P.: An array
operator would make collection classes much nicer.

With Regards

Martin

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-03  2:56 ` Fionn mac Cuimhaill
  2003-06-03 14:02   ` Matthew Heaney
@ 2003-06-03 16:23   ` Mário Amado Alves
  2003-06-05 19:02     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 21+ messages in thread
From: Mário Amado Alves @ 2003-06-03 16:23 UTC (permalink / raw)


> >    function "()" ( Source : in Array_Like_Type;
> >                    Index  : in Index_Type )
> >       return Component_Type;
>
>  To go along with this, a way to define a slice of an
> Array_Like_Type would be nice.

Great idea!

function "()"
  (Source : in Array_Like_Type;
   From : in Index_Type;
   To : in Index_Type)
  return Array_Like_Type;

Or "(..)".

Yes, Matthew, it's just syntax. So are the (already) redefineable
operators. But it's really useful, no? Compare e.g.
  ...
  +"Marius",
  +"Matthew",
  ...
to
  ...
  new String' ("Marius"),
  new String' ("Matthew"),
  ...

Actually the fact that it's just syntax might facilitate getting it
approved :-)

BTW, I think that if a standard containers library is included in 200X
then Ada.Strings.Unbounded and the like should be revised in terms of
it. It would drastically reduce the size of the specs. It would
suffice to say something like

  Unbounded_String is equivalent to the container type
  of an instantiation of Ada.Containers.Arrays.Unbounded
  with the type Character.

--Marius



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-02 23:42 ` Matthew Heaney
  2003-06-03 14:59   ` Frank J. Lhota
@ 2003-06-03 19:52   ` Francisco Javier Loma Daza
  1 sibling, 0 replies; 21+ messages in thread
From: Francisco Javier Loma Daza @ 2003-06-03 19:52 UTC (permalink / raw)


mheaney@on2.com (Matthew Heaney) wrote in message news:<1ec946d1.0306021542.58714996@posting.google.com>...
> "Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> wrote in message news:<V0LCa.32473$ca5.11277@nwrdny02.gnilink.net>...
> > There appears to be wide agreement that Ada 200X should include some sort of
> > standard container library like Charles and PragMark. This library will
> > probably include generic packages for creating and operating with dynamic
> > lists and maps. One can view these kinds of collections as generalized
> > arrays, and as such, it would be nice to use array notation for accessing a
> > member of one of these collections. 
> >
>  [snip]
> > I cannot help but think that this would be of tremendous help with whatever
> > standard container library is added to Ada 200X.
> 
> But all you've done is change the syntax.  None of your suggestions
> allow you to do more than is already provided by the library.
> 

Yes, I can first make a prototype using arrays, and when a more
dynamic structure is needed switch to a Single_List. If Single_List
have the same syntax of an array (operator (), and some attributes), I
have not to change a line of code. The same example with
Unbounded_String and String .... I know that I can do generics for
that purpouse, but then loosing all the syntactic richness/sugar.
Providing a consistent notation/syntax for arrays and user defined
containers would make the code look like better, isn't readability an
Ada goal?

Ada have very good support for basic types, why not have the same
support for user defined types?

> [snip]
[snip] 
> If you're going to make a change in the syntax of the language, then
> it has be because it allows you to do something you can't do already. 

Yes, I can live without that ... but then I will have to rewrite (and
retest) a lot of lines of code. Having that will make more readable my
code by not to worry about how every particular collection is defined.

[snip]
> For example, there's no way to declare an access subtype right now
> that means "all the access values except null."  A useful language
> change would be to allow the declaration:
> 
>   type Element_Access_Base is access all Element_Type;
> 
>   subtype Element_Access is Element_Access_Base range not null;

I like your proposal very much!!!



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-03 14:59   ` Frank J. Lhota
  2003-06-03 15:09     ` Frank J. Lhota
  2003-06-03 16:04     ` Martin Krischik
@ 2003-06-03 20:24     ` Randy Brukardt
  2 siblings, 0 replies; 21+ messages in thread
From: Randy Brukardt @ 2003-06-03 20:24 UTC (permalink / raw)


Frank J. Lhota wrote in message ...
>"Matthew Heaney" <mheaney@on2.com> wrote in message
>news:1ec946d1.0306021542.58714996@posting.google.com...
>> If you're going to make a change in the syntax of the language, then
>> it has be because it allows you to do something you can't do already.
>> For example, there's no way to declare an access subtype right now
>> that means "all the access values except null."  A useful language
>> change would be to allow the declaration:
>>
>>   type Element_Access_Base is access all Element_Type;
>>
>>   subtype Element_Access is Element_Access_Base range not null;
>
>This is an interesting idea, and we should probably pursue it further
in
>another. Constraint checking has always been tremendously helpful.
There is
>one potential (but not insurmountable) problem with this proposal: in
the
>absence of explicit initializations, an access variable is initialized
to
>null.


Already done. See AI-00231. (But there are some problems with doubly
constrained subtypes, so it is not yet finished.)

         Randy.





^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-03 16:04     ` Martin Krischik
@ 2003-06-04 17:28       ` Matthew Heaney
  2003-06-04 18:21         ` Frank J. Lhota
  0 siblings, 1 reply; 21+ messages in thread
From: Matthew Heaney @ 2003-06-04 17:28 UTC (permalink / raw)


Martin Krischik <krischik@users.sourceforge.net> wrote in message news:<1325634.ddflWlv0t0@linux1.krischik.com>...
> 
> I agree with your point and put my vote in favour of the O.P.: An array
> operator would make collection classes much nicer.

The problem is what type to return.  In C++ I do this:

  T& operator[]();
  const T& operator[]() const;

The operator returns a reference to T.  There are no reference types
in Ada, so it's not obvious how the language would be able to provide
it.



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-04 17:28       ` Matthew Heaney
@ 2003-06-04 18:21         ` Frank J. Lhota
  2003-06-05  1:15           ` Robert I. Eachus
  0 siblings, 1 reply; 21+ messages in thread
From: Frank J. Lhota @ 2003-06-04 18:21 UTC (permalink / raw)


"Matthew Heaney" <mheaney@on2.com> wrote in message
news:1ec946d1.0306040928.6eb47667@posting.google.com...
> The problem is what type to return.  In C++ I do this:
>
>   T& operator[]();
>   const T& operator[]() const;
>
> The operator returns a reference to T.  There are no reference types
> in Ada, so it's not obvious how the language would be able to provide
> it.

I debated whether the right solution was to introduce some notion of
reference types to Ada, so that the "()" functions would be declared
something like this:

    function "()" ( Source : in Array_Like_Type;
                    Index  : in Index_Type )
       return access Component_Type;

This would parallel the C++ approach, and has worked very well in that
realm. It occurred to me, however, that the reference type approach is
assumes that in an object of a array-like type, each component is
represented as an aliased section of memory of type Component_Type. One can
easily think of many situations where this would not be the case:

    - the components might be stored in the array-like object in a packed
format, so that they cannot be aliased;
    - the array-like object may be implemented using a file or database, so
that the components are not in memory;
    - the components may be stored in some alternate representation;

The reference type approach breaks down in these cases. As an alternative, I
proposed separate "()" and "():=" for retrieving and assigning components in
an array-like object.

    -- Function used to evaluate Source( Index )
    function "()" ( Source : in Array_Like_Type;
                    Index  : in Index_Type )
       return Component_Type;

    -- Procedure for assigning Value to Source( Index )
    procedure "():=" ( Source : in out Array_Like_Type;
                       Index  : in     Index_Type;
                       Value  : in     Component_Type );

This approach makes very minimal assumptions about our array-like types:
that we can retrieve a component from such an object given an index value,
and that we can assign a component value at a given index. These assumptions
would hold for virtually any type for which one would care to use the array
notation. Moreover, the "()" and "():=" proposal does not require adding
reference types to Ada.





^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-04 18:21         ` Frank J. Lhota
@ 2003-06-05  1:15           ` Robert I. Eachus
  2003-06-05 14:59             ` Frank J. Lhota
  2003-06-05 17:25             ` Matthew Heaney
  0 siblings, 2 replies; 21+ messages in thread
From: Robert I. Eachus @ 2003-06-05  1:15 UTC (permalink / raw)


Frank J. Lhota wrote:

> The reference type approach breaks down in these cases. As an alternative, I
> proposed separate "()" and "():=" for retrieving and assigning components in
> an array-like object.
> 
>     -- Function used to evaluate Source( Index )
>     function "()" ( Source : in Array_Like_Type;
>                     Index  : in Index_Type )
>        return Component_Type;
> 
>     -- Procedure for assigning Value to Source( Index )
>     procedure "():=" ( Source : in out Array_Like_Type;
>                        Index  : in     Index_Type;
>                        Value  : in     Component_Type );
> 
> This approach makes very minimal assumptions about our array-like types:
> that we can retrieve a component from such an object given an index value,
> and that we can assign a component value at a given index. These assumptions
> would hold for virtually any type for which one would care to use the array
> notation. Moreover, the "()" and "():=" proposal does not require adding
> reference types to Ada.

I like the idea, but there are some practical problems.  First, a 
property of arrays in Ada, is that several attributes are currently 
predefined.  For Foo(Foo'First) to work correctly, you need user defined 
attributes.  Fortunately, the syntax is already "in there," but the 
attributes that can be defined would have to be extended, and there 
would probably be a rule required that when you defined an "()" 
function, the 'First, 'Last, 'Length, and 'Range attributes would become 
abstract and need to be overridden befor you could use the type.

Also, I think that procedure "()" makes more sense, but that is just 
nomenclature.  What is not nomenclature is that Ada already allows 
functions as prefixes on the left-hand side of assignment statements! 
(The function has to return an access type, but from there on everything 
works like you would expect.)  So I recommend instead:

     -- Function used to evaluate Source( Index )
     function "()" ( Source : in Array_Like_Type;
                     Index  : in Index_Type )
        return Component_Type;

     for Source'First use My_First;
     for Source'Last use My_Last;
     -- I think that allowing a definition of 'Range other than
     -- Source'First..Source'Last would require too much invention.
     -- Given that, Source'Length can be defined as
     -- Index_Type'Pos(Source'Last) - Index_Type'Pos(Source'First) + 1.

     -- function for assigning Value to Source( Index )
     function "()" ( Source : in out Array_Like_Type;
                     Index  : in     Index_Type)
        return Component_Type'Access;

Yes, that does though have the effect that for some types with packed 
representations you are not going to be able to define the second 
operation, so you must still use a procedure call to do the 
modification.  But it should work fine for sparse array implementations.






^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-05  1:15           ` Robert I. Eachus
@ 2003-06-05 14:59             ` Frank J. Lhota
  2003-06-05 17:25             ` Matthew Heaney
  1 sibling, 0 replies; 21+ messages in thread
From: Frank J. Lhota @ 2003-06-05 14:59 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@attbi.com> wrote in message
news:3EDE998D.3060701@attbi.com...
> I like the idea, but there are some practical problems.  First, a
> property of arrays in Ada, is that several attributes are currently
> predefined.  For Foo(Foo'First) to work correctly, you need user defined
> attributes.  Fortunately, the syntax is already "in there," but the
> attributes that can be defined would have to be extended, and there
> would probably be a rule required that when you defined an "()"
> function, the 'First, 'Last, 'Length, and 'Range attributes would become
> abstract and need to be overridden befor you could use the type.

In other words, why not allow the programmer to specify, in a standard
fashion, an iteration sheme (similar to the C++ iterators) for visiting each
index in a container object? Ada already has a lot of the intrasturcture
there, with the 'First, 'Last, 'Succ and 'Pred attributes. This idea has a
lot of merit, and should be explored further. It would be very nice if Ada0x
was designed so that a programmer could write

    for I in Foo'Range loop
        ...
    end loop;

for a user-defined array-like type.

> Also, I think that procedure "()" makes more sense, but that is just
> nomenclature.  What is not nomenclature is that Ada already allows
> functions as prefixes on the left-hand side of assignment statements!
> (The function has to return an access type, but from there on everything
> works like you would expect.)  So I recommend instead:
>
>      -- Function used to evaluate Source( Index )
>      function "()" ( Source : in Array_Like_Type;
>                      Index  : in Index_Type )
>         return Component_Type;
>
>      for Source'First use My_First;
>      for Source'Last use My_Last;
>      -- I think that allowing a definition of 'Range other than
>      -- Source'First..Source'Last would require too much invention.
>      -- Given that, Source'Length can be defined as
>      -- Index_Type'Pos(Source'Last) - Index_Type'Pos(Source'First) + 1.
>
>      -- function for assigning Value to Source( Index )
>      function "()" ( Source : in out Array_Like_Type;
>                      Index  : in     Index_Type)
>         return Component_Type'Access;
>
> Yes, that does though have the effect that for some types with packed
> representations you are not going to be able to define the second
> operation, so you must still use a procedure call to do the
> modification.  But it should work fine for sparse array implementations.

Granted, the function returning Component_Type'Access would work in many
cases, but I still think that the most general and powerful approach is to
have the "()" function and "():=" procedure. Consider an instantiation of
Ada.Direct_Io:

    type Element_Type is record ... end record;
    package Element_Io is new Ada.Direct_Io( Element_Type );
    use Element_Io;

    My_File : Element_Io.File_Type;

An open file of type Element_Io.File_Type can be thought of as an array of
objects of type Element_Type. In fact, one could view such a file as an
array of Element_Type objects that are stored in a random access file
instead of memory. Given this view, why not use array notation for the
handling the contents of this file? With the "()" and "():=" operators, we
could extend Ada.Direct_Io so that

    Read( File => My_File,
          Item => My_Element,
          From => Index );

could also be written (using the "()" function) as

    My_Element := My_File( Index );

Conversely, the "():=" procedure can be used to write to the file, i.e.
instead of writing

    Write( File => My_File,
           Item => My_Element,
           To   => Index );

the programmer would be able to write

    My_File( Index ) := My_Element;







^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-05  1:15           ` Robert I. Eachus
  2003-06-05 14:59             ` Frank J. Lhota
@ 2003-06-05 17:25             ` Matthew Heaney
  1 sibling, 0 replies; 21+ messages in thread
From: Matthew Heaney @ 2003-06-05 17:25 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@attbi.com> wrote in message news:<3EDE998D.3060701@attbi.com>...
> 
> Also, I think that procedure "()" makes more sense, but that is just 
> nomenclature.  What is not nomenclature is that Ada already allows 
> functions as prefixes on the left-hand side of assignment statements! 
> (The function has to return an access type, but from there on everything 
> works like you would expect.)  So I recommend instead:

That's essentially why you don't really need this change in the
language.  I gave the example:

  To_Access (I).all := X;

which does almost what you want.  Instead of dereferencing a named
iterator object, you could do this (ignoring the fact that Find can
fail):

  To_Access (Find (Map, Key)).all := X;

Of course, you could have Find return an access type directly:

  Find (Map, Key).all := X;

No, this is not as simple as:

  Map [Key] := X;

but it's pretty close.

One thing I would like, in lieu of proper reference types, is to limit
what a user is allowed to do with an access type, e.g.

  type Element_Access is limited access all Element_Type;

or better yet

  type Element_Access (<>) is limited access all Element_Type;

This would prevent the user from hanging on to the access object
returned by Find.

The C++ index operator can modify the map, to implicitly insert the
key and construct the associated element with its default value; this
allows you to do this (because scalars are initialized to 0):

   ++map[key];

To provide this feature in Ada you'll have to pass the map as an
access parameter:

   Set (Map'Access, Key).all := X;

This inserts the key into the map if it wasn't already in the map.  To
implement this using Charles, it's simple enough:

   function Set 
     (Map : access Map_Subtype;
      Key : in Key_Subtype) return Element_Access is

      I : Iterator_Type;
      B : Boolean;
   begin
      Insert (Map.all, Key, I, B);
      return To_Access (I);
   end; 

Of course, if the map object is visible at the point of declaration of
Set, then you can get rid of the map parameter, reducing the syntax
to:

   Set (Key).all := X;

http://home.earthlink.net/~matthewjheaney/charles/

I have a new release almost ready to go, containing new set and map
containers that allow you to store elements that have a limited type. 
For example, this would allow you to create a set of files, with the
file name as the key:

package File_Sets is
   new Charles.Sets.Sorted.Limited_Unbounded
     (Key_Type => String,
      Element_Type => Ada.Text_IO.File_Type);

[There's also a hashed version.]

procedure Open 
  (Set  : in out File_Sets.Container_Type;
   Name : in     String) is

   I : Iterator_Type;
   B : Boolean;
begin
   Insert (Set, Name, I, B);

   if B then
      declare
         F : File_Type renames To_Access (I).all;
      begin
         Open (F, In_File, Name);
      end;
   else
      declare
         F : File_Type renames To_Access (I).all;
      begin
         if not Is_Open (F) then
            Open (F, In_File, Name);
         end if;
      end;
   end if;
end Open;

In you're interested, drop me a line.

-Matt



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-03 16:23   ` Mário Amado Alves
@ 2003-06-05 19:02     ` Dmitry A. Kazakov
  2003-06-06 10:56       ` Mário Amado Alves
  0 siblings, 1 reply; 21+ messages in thread
From: Dmitry A. Kazakov @ 2003-06-05 19:02 UTC (permalink / raw)


Mário Amado Alves wrote:

>> >    function "()" ( Source : in Array_Like_Type;
>> >                    Index  : in Index_Type )
>> >       return Component_Type;
>>
>>  To go along with this, a way to define a slice of an
>> Array_Like_Type would be nice.
> 
> Great idea!
> 
> function "()"
>   (Source : in Array_Like_Type;
>    From : in Index_Type;
>    To : in Index_Type)
>   return Array_Like_Type;
> 
> Or "(..)".

IMO one should first add a new set of types: "index" types. With some set of 
predefined operations. Then you define sets over index types. "range" is an 
example of such a set. More interesting would be "column", "row" for a 
multi-dimensional index. (Ada does not have slices of multi-dimensional 
arrays). Then a square subset (specifies submatrix). Then a diagonal set 
... ad infinum. (:-))

Only when you have proper index types, you can start to play with operations 
like slices and enumeration (in for-statement).

If you have true index types and objects, you will need only one ()!

function "()"
(  Source : in Array_Like_Type;
   Index  : Index_Like_Type
)  return ?

The problem is that, what the function returns, depends on how the index 
argument is constrained.

This brings back a very important point of dealing with type constraints in 
a more general way than Ada presently does. For instance to allow () 
described above, one should treat:

type Element is ...
type Vector is array (Index_1) of Element;
type Matrix is array (Index_1, Index_2) of Element;

as differenty constrained subtypes of the same type Matrix. Both 
discriminants and tags can be considered type constraints. Then there are 
two major problems:

1. There has to be a way to remove statically known constraints.

2. There has to be a way to evaluate constraints in an independent body 
(from the original procedure body).

> Yes, Matthew, it's just syntax. So are the (already) redefineable
> operators. But it's really useful, no? Compare e.g.
>   ...
>   +"Marius",
>   +"Matthew",
>   ...
> to
>   ...
>   new String' ("Marius"),
>   new String' ("Matthew"),
>   ...
> 
> Actually the fact that it's just syntax might facilitate getting it
> approved :-)
> 
> BTW, I think that if a standard containers library is included in 200X
> then Ada.Strings.Unbounded and the like should be revised in terms of
> it. It would drastically reduce the size of the specs. It would
> suffice to say something like
> 
>   Unbounded_String is equivalent to the container type
>   of an instantiation of Ada.Containers.Arrays.Unbounded
>   with the type Character.

Oh that's for sure. For example:

   type X is tagged something;

      is an equivalent to

   type X is something;
   pragma Embedded_Tag (X);
---
   type X is limited something;

      is an equivalent to

   type X is something;
   procedure ":=" (L : in out X; R : Y) is null;
---
   ...

-- 
Regards,
Dmitry A. Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-05 19:02     ` Dmitry A. Kazakov
@ 2003-06-06 10:56       ` Mário Amado Alves
  2003-06-06 16:55         ` Chad R. Meiners
                           ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Mário Amado Alves @ 2003-06-06 10:56 UTC (permalink / raw)


> IMO one should first add a new set of types: "index" types. (Dmitry)

Maybe *every* 'conceptual' type should be in the type system.
A la Smalltalk.
This includes exceptions (cf. AE'2001) and, yes, ranges.
It always bugged me what is the 'return type' of the Range attribute.
I think it's the only attribute that does not return a type proper.
Even exceptions and tags have their 'surrogates' in the type system.
I can see "I .. J" as sugar for "Range (From => I, To => J)".
".." as an operator!
But this be too much to prepare for Ada 200Y :-(
Ada 20XX maybe, if we're still around :-)



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-06 10:56       ` Mário Amado Alves
@ 2003-06-06 16:55         ` Chad R. Meiners
  2003-06-06 19:01         ` Frank J. Lhota
  2003-06-07  8:36         ` Dmitry A. Kazakov
  2 siblings, 0 replies; 21+ messages in thread
From: Chad R. Meiners @ 2003-06-06 16:55 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 264 bytes --]


"M�rio Amado Alves" <maa@liacc.up.pt> wrote in message
news:4a4de33a.0306060256.52b12d70@posting.google.com...
> It always bugged me what is the 'return type' of the Range attribute.

You're not the only one ;)

http://www.cse.msu.edu/~meinersc/ranges.html





^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-06 10:56       ` Mário Amado Alves
  2003-06-06 16:55         ` Chad R. Meiners
@ 2003-06-06 19:01         ` Frank J. Lhota
  2003-06-09 14:15           ` Matthew Heaney
  2003-06-07  8:36         ` Dmitry A. Kazakov
  2 siblings, 1 reply; 21+ messages in thread
From: Frank J. Lhota @ 2003-06-06 19:01 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1679 bytes --]

"M�rio Amado Alves" <maa@liacc.up.pt> wrote in message
news:4a4de33a.0306060256.52b12d70@posting.google.com...
> > IMO one should first add a new set of types: "index" types. (Dmitry)
>
> Maybe *every* 'conceptual' type should be in the type system.
> A la Smalltalk.
> This includes exceptions (cf. AE'2001) and, yes, ranges.
> It always bugged me what is the 'return type' of the Range attribute.
> I think it's the only attribute that does not return a type proper.
> Even exceptions and tags have their 'surrogates' in the type system.
> I can see "I .. J" as sugar for "Range (From => I, To => J)".
> ".." as an operator!

This would dovetail nicely with the idea of an Ada iterator schemes. The
"range" object could encapsulate the notion of an oredered list of values.
Each Range object would a 'First element and a 'Last element, as well as the
'Succ / 'Pred functions to move forward / backward through the values in the
range. If Ada 200X had a range object, it would be nice to be able to define
the "in" operator for it. Moreover, it would be great if the "for" loop
could work with range objects, i.e.

    for I in Range_Object loop ... end loop;

would execute the loop body with I set to each value in Range_Object,
visited in Forward order, starting at 'First and ending with 'Last.
Similarly

    for I in reverse Range_Object loop ... end loop;

would visit the values in Range_Objec in reverse order, i.e. starting with
'Last, then moving towards 'First using the 'Pred function.

> But this be too much to prepare for Ada 200Y :-(
> Ada 20XX maybe, if we're still around :-)

I plan to live to be 100, although I might not be programming at that time.





^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-06 10:56       ` Mário Amado Alves
  2003-06-06 16:55         ` Chad R. Meiners
  2003-06-06 19:01         ` Frank J. Lhota
@ 2003-06-07  8:36         ` Dmitry A. Kazakov
  2 siblings, 0 replies; 21+ messages in thread
From: Dmitry A. Kazakov @ 2003-06-07  8:36 UTC (permalink / raw)


Mário Amado Alves wrote:

>> IMO one should first add a new set of types: "index" types. (Dmitry)
> 
> Maybe *every* 'conceptual' type should be in the type system.
> A la Smalltalk.

Every conceptual type a programmer might imagine. That's the difference 
between ADT and non-ADT. Alas, there is no ADT for 2nd-order types (type 
sets like (<>), range (<>), mod (<>) etc) in Ada. That has to be changed. 

Another weakness is absense of supertypes. It is impossible to develop a 
type hierarchy before coding in a project of real size. Especially it is 
true for Ada as opposed to "run-once" languages. So if I want to mix String 
and Unbounded_String let me do it.

> This includes exceptions (cf. AE'2001) and,

I am not sure that exceptions should be of different types. To have classes 
of exceptions one just need them to be ordered in some way. Type hierarchy 
brings an order, but other, undesirable effects, as well. I would prefer an 
ordered set of exceptions of same (index) type. With index types one could 
do something like:

IO_Errors : exception'Set := End_Error..Use_Error;
...
exception
   when IO_Errors =>

> yes, ranges.
> It always bugged me what is the 'return type' of the Range attribute.
> I think it's the only attribute that does not return a type proper.
> Even exceptions and tags have their 'surrogates' in the type system.
> I can see "I .. J" as sugar for "Range (From => I, To => J)".
> ".." as an operator!

And "|" as an operator!

Then somebody (me?) whould ask for:

Prime_Numbers : Integer'Set := 1 | 3 | 5 | 7 | 11 | 13;
type Primes is Integer Prime_Numbers; -- (:-))

> But this be too much to prepare for Ada 200Y :-(
> Ada 20XX maybe, if we're still around :-)

--
Regards,
Dmitry A. Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: Adding "()" operator to Ada 200X
  2003-06-06 19:01         ` Frank J. Lhota
@ 2003-06-09 14:15           ` Matthew Heaney
  0 siblings, 0 replies; 21+ messages in thread
From: Matthew Heaney @ 2003-06-09 14:15 UTC (permalink / raw)


"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> wrote in message news:<uy5Ea.14478$b8.437@nwrdny03.gnilink.net>...
> 
> This would dovetail nicely with the idea of an Ada iterator schemes. The
> "range" object could encapsulate the notion of an oredered list of values.
> Each Range object would a 'First element and a 'Last element, as well as the
> 'Succ / 'Pred functions to move forward / backward through the values in the
> range. 

You can already do this.  In the Charles library, every container is
indeed "an ordered list of values," which you can navigate using
either active or passive iterators.

Each container has selector functions that return iterator objects
designating the first and last elements in the container (and keys, if
this is a map), as well as the nonce elements immediately after the
last element and immediately before the first element.


> If Ada 200X had a range object, it would be nice to be able to define
> the "in" operator for it. Moreover, it would be great if the "for" loop
> could work with range objects, i.e.
> 
>     for I in Range_Object loop ... end loop;
> 
> would execute the loop body with I set to each value in Range_Object,
> visited in Forward order, starting at 'First and ending with 'Last.

Just do this:

procedure Op (C : Container_Subtype) is
   I : Iterator_Type := First (C);
   J : constant Iterator_Type := Back (C);
begin
   while I /= J loop
      declare
         E : constant Element_Type := Element (I);
      begin
         Do_Someting (E);
      end;

      I := Succ (I);
   end loop;
end Op;

--or this:

procedure Op (C : Container_Subtype) is

   procedure Iterate is
     new Generic_Select_Elements (Do_Something);
begin
   Iterate (First (C), Back (C));
end Op;



> Similarly
> 
>     for I in reverse Range_Object loop ... end loop;
> 
> would visit the values in Range_Objec in reverse order, i.e. starting with
> 'Last, then moving towards 'First using the 'Pred function.

Just do this:

procedure Op (C : Container_Subtype) is
   I : Iterator_Type := Last (C);
   J : constant Iterator_Type := Front (C);
begin
   while I /= J loop
      declare
         E : constant Element_Type := Element (I);
      begin
         Do_Someting (E);
      end;

      I := Pred (I);
   end loop;
end Op;

--or this:

procedure Op (C : Container_Subtype) is

   procedure Iterate is
     new Generic_Reverse_Select_Elements (Do_Something);
begin
   Iterate (Last (C), Front (C));
end Op;

No change in Ada language syntax is necessary.



^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2003-06-09 14:15 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-02 16:35 Adding "()" operator to Ada 200X Frank J. Lhota
2003-06-02 23:42 ` Matthew Heaney
2003-06-03 14:59   ` Frank J. Lhota
2003-06-03 15:09     ` Frank J. Lhota
2003-06-03 16:04     ` Martin Krischik
2003-06-04 17:28       ` Matthew Heaney
2003-06-04 18:21         ` Frank J. Lhota
2003-06-05  1:15           ` Robert I. Eachus
2003-06-05 14:59             ` Frank J. Lhota
2003-06-05 17:25             ` Matthew Heaney
2003-06-03 20:24     ` Randy Brukardt
2003-06-03 19:52   ` Francisco Javier Loma Daza
2003-06-03  2:56 ` Fionn mac Cuimhaill
2003-06-03 14:02   ` Matthew Heaney
2003-06-03 16:23   ` Mário Amado Alves
2003-06-05 19:02     ` Dmitry A. Kazakov
2003-06-06 10:56       ` Mário Amado Alves
2003-06-06 16:55         ` Chad R. Meiners
2003-06-06 19:01         ` Frank J. Lhota
2003-06-09 14:15           ` Matthew Heaney
2003-06-07  8:36         ` Dmitry A. Kazakov

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