comp.lang.ada
 help / color / mirror / Atom feed
* The "()" operator revisited.
@ 2004-01-12 17:53 Frank J. Lhota
  2004-01-12 18:38 ` Frank J. Lhota
                   ` (3 more replies)
  0 siblings, 4 replies; 45+ messages in thread
From: Frank J. Lhota @ 2004-01-12 17:53 UTC (permalink / raw)


Last June, I proposed that in order to provide an abstract array capability,
Ada 0y should support  user-defined "()" and "():="operators. Since this
issue has come up again, I would like to summarize and expand on this
proposal.

Note: the following discussion probably has an insufficient amount of
legalese to satisfy language lawyers. Once we've thrashed out these ideas,
I'll be happy to work with anyone with formalizing this proposal.

The idea is that container libraries, such as the Booch components, Charles
and PragMark, often include collection objects that can be viewed as
generalized arrays. Undoubtedly, the next standard will have some variation
of these container libraries. In support of these generalized arrays, Ada
should allow the array notation to be used for these object. To this end, I
propose adding two operators Ada. The "()" operator, used for reading a
component of an abstract array, has the form:

    function "()" ( Source  : in Abstract_Array_Type;
                    Index_1 : in Index_Type_1;
                    Index_2 : in Index_Type_2;
                    ...
                    Index_N : in Index_Type_N )
       return Component_Type;

Used to write a component of an abstract array, the "():=" operator has the
form

    procedure "():=" ( Source  : in out Abstract_Array_Type;
                       Index_1 : in Index_Type_1;
                       Index_2 : in Index_Type_2;
                       ...
                       Index_N : in Index_Type_N;
                       Value   : in Component_Type );

For a standard array type of the form

    type An_Array is array ( Index_Type_1 range <>, Index_Type_2 range <>,
... ) of Component_Type;

the "()" and "():=" operators are predefined. The predefined versions of
these operators are implicit. For packed arrays, the predefined versions of
"()" and "():="does the usual mask and shift operations to unpack or pack
the given component.

When the "()" function is defined and visible for the type Abstract_Array_Ty
pe, and A is a (possibly constant) object of type Abstract_Array_Type, then
the expression

    A( Index_1, Index_2, ... Index_N )

evaluates to

    "()"( A, Index_1, Index_2, ... Index_N )

Note that the "()" also provides support for an abstract function call
facility.

The "()" operator suffices for presenting a read-only view of a component of
an abstract array type. The "():=" is used in conjunction with "()" to
provide a variable view of an abstract array component. When "():=" operator
is defined and visible for Abstract_Array_Type, and A is a non-constant
object of type Abstract_Array_Type, then the expression

    A( Index_1, Index_2, ... Index_N )

can be assigned a Value of type Component_Type. This assignment is done by
performing the call

    "():="( A, Index_1, Index_2, ... Index_N, Value );

This "():=" call would also be used if A( Index_1, Index_2, ... Index_N ) is
used as an actual parameter for a parameter of mode "out"

When both "()" and "():=" operators are visible for Abstract_Array_Type,
then the expression

    A( Index_1, Index_2, ... Index_N )

can be used as an "in out" parameter. If we have the subprogram

    procedure Fiddle( Item : in out Component_Type );

Then the call

    Fiddle( A( I_1, I_2, ... I_N ) );

is basically equivalent to

    declare
       Temp_Comp : Component_Type := A( I_1, I_2, ... I_N );
    begin
       Fiddle( Temp_Comp );
       A( I_1, I_2, ... I_N ) := Temp_Comp;
    end;

except that the indices are evaluated only once. Note: something like this
is done in Ada95, when dealing with packed arrays.

We can easily define these operators for abstract arrays in Ada95. In the
string package Ada.Strings.Unbounded, we could add

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

    procedure "():=" (Source : in out Unbounded_String;
                      Index  : in     Positive;
                      By     : in     Character)
       renames Replace_Element;

Similar declarations can be added to Ada.Strings.Bounded. This would permit
the higher-level Ada string types to use the same notation as the low-level
standard String type.

Also, one can easily view a Direct I/O file as an abstract array. The
package Ada.Direct_Io can inline the following versions of "()" and "():="
for File_Type:

    function "()" (File  : in File_Type;
                   Index : in Positive_Count)
                   return     Element_Type
    is
       Result : Element_Type;
    begin
       Read( File, Result, From => Index );
       return Result
    end "()";

    procedure "():=" (File  : in File_Type;
                      Index : in Positive_Count;
                      Item  : in Element_Type)
    is
    begin
       Write( File, Item, To => Index );
    end "():=";

A controversial idea: when "()" and "():=" is visible for
Abstract_Array_Type, and A is a non-constant object of type
Abstract_Array_Type, should we allow a declaration like this:

    An_Object : Component_Type renames A( I_1, I_2, I_3, ... I_N );

The idea is that this is a "virtual" object of type Component_Type, where
calls to "()" and "():=" are used to read and write the values of this
object. I'm not entirely sure that this type of "renames" declaration is a
good idea, but I'm interested in what others in this NG think of this.





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

* Re: The "()" operator revisited.
  2004-01-12 17:53 The "()" operator revisited Frank J. Lhota
@ 2004-01-12 18:38 ` Frank J. Lhota
  2004-01-12 22:26 ` Robert A Duff
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 45+ messages in thread
From: Frank J. Lhota @ 2004-01-12 18:38 UTC (permalink / raw)


"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> wrote in message
news:raBMb.9128$Qq.7455@nwrdny01.gnilink.net...
> Also, one can easily view a Direct I/O file as an abstract array. The
> package Ada.Direct_Io can inline the following versions of "()" and "():="
> for File_Type:
>
>     function "()" (File  : in File_Type;
>                    Index : in Positive_Count)
>                    return     Element_Type
>     is
>        Result : Element_Type;
>     begin
>        Read( File, Result, From => Index );
>        return Result
>     end "()";
>
>     procedure "():=" (File  : in File_Type;
>                       Index : in Positive_Count;
>                       Item  : in Element_Type)
>     is
>     begin
>        Write( File, Item, To => Index );
>     end "():=";

My apologies, that should have read:

    function "()" (File  : in File_Type;
                   Index : in Positive_Count)
                   return     Element_Type
    is
       Result : Element_Type;
    begin
       Read( File, Result, From => Index );
       return Result;
    end "()";

    procedure "():=" (File  : in out File_Type;
                      Index : in     Positive_Count;
                      Item  : in     Element_Type)
    is
    begin
       Write( File, Item, To => Index );
    end "():=";





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

* Re: The "()" operator revisited.
  2004-01-12 17:53 The "()" operator revisited Frank J. Lhota
  2004-01-12 18:38 ` Frank J. Lhota
@ 2004-01-12 22:26 ` Robert A Duff
  2004-01-13 16:29   ` Frank J. Lhota
  2004-01-13  9:24 ` Dmitry A. Kazakov
  2004-01-13 13:13 ` Marin David Condic
  3 siblings, 1 reply; 45+ messages in thread
From: Robert A Duff @ 2004-01-12 22:26 UTC (permalink / raw)


"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> writes:

> Last June, I proposed that in order to provide an abstract array capability,
> Ada 0y should support  user-defined "()" and "():="operators. Since this
> issue has come up again, I would like to summarize and expand on this
> proposal.

This is a good idea.  As you note below, it's got a long way to go
before you've got a list of wording changes to the RM.  For example, the
notion of operator-named *procedures* does not currently exist in Ada.
But before bothering with that, I think there are some important
issues to work out:

You seem to be saying that components of arrays (or just abstract
arrays?) are always passed by copy.  That seems like a real problem,
since for efficiency, most compilers pass large things by reference.
(I'm talking about the case of array-of-large-array or
array-of-large-record.)

Furthermore, if the component type is limited, it is *required* to be
passed by reference.  This raises the question: can "():=" be declared
for limited types?

What does A(I)'Access mean in this scheme?

Are there interactions with Adjust, which is normally called for
assignment of nonlimited controlled types?

You seem to treat 'out' parameters as copy-out only.  But for composite
types, 'out' means pretty much the same thing as 'in out' -- at least
*some* parts of the object are copied *in* (see RM for details).
Likewise, if the component type is an access type, you can't allow
undefined values to be created -- all access objects have to be
initialized to 'null' if they aren't initialized to something else
meaningful.

You seemed to be hoping that this new notation could underly the
definition of the *existing* array indexing semantics.  That would be
elegant.  However, some of the above issues mean it doesn't work -- at
least as you've defined it so far.

> Note: the following discussion probably has an insufficient amount of
> legalese to satisfy language lawyers. Once we've thrashed out these ideas,
> I'll be happy to work with anyone with formalizing this proposal.

I hate to be discouraging, but my guess is that a proposal like this is
*not* going to be accepted by the ARG, even if were written up as proper
RM wording changes.

> Similar declarations can be added to Ada.Strings.Bounded. This would permit
> the higher-level Ada string types to use the same notation as the low-level
> standard String type.

Well, it allows that for the particular notation of array indexing,
and that would be a good thing.  But it doesn't completely solve
the problem.  It doesn't support slice notation (but I don't think
slices are all that important).  And it doesn't support string literal
notation -- I think that *is* important -- it's really annoying that you
can't have a string literal of type uunbounded string.  Similarly, it
doesn't support aggregate notation.

If I were designing a language from scratch, I would allow user-defined
meanings for all of the above notations.  But as I said, unfortunately,
I don't see this happening for Ada 0X.

- Bob



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

* Re: The "()" operator revisited.
  2004-01-12 17:53 The "()" operator revisited Frank J. Lhota
  2004-01-12 18:38 ` Frank J. Lhota
  2004-01-12 22:26 ` Robert A Duff
@ 2004-01-13  9:24 ` Dmitry A. Kazakov
  2004-01-13 16:44   ` Frank J. Lhota
  2004-01-13 13:13 ` Marin David Condic
  3 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2004-01-13  9:24 UTC (permalink / raw)


On Mon, 12 Jan 2004 17:53:27 GMT, "Frank J. Lhota"
<NOSPAM.lhota.adarose@verizon.net> wrote:

>Last June, I proposed that in order to provide an abstract array capability,
>Ada 0y should support  user-defined "()" and "():="operators. Since this
>issue has come up again, I would like to summarize and expand on this
>proposal.
>
>Note: the following discussion probably has an insufficient amount of
>legalese to satisfy language lawyers. Once we've thrashed out these ideas,
>I'll be happy to work with anyone with formalizing this proposal.

[...skipped...]

The major question. Would it really be an abstract array? It seems it
would not. More specifically, how would it be matched against a formal
generic array parameter? To be matched one need, in addition to
indexing, also define slices, index ranges and array attributes. This
means that the proposal should include a way to define all that. Then
of course, there has to be a syntactic suggar telling the compiler
that the type being declared is an abstract array, so that the
compiler could check that (), slices, ranges, attributes are indeed
implemented. Summarizing:

1. There has to be a formal definition of the abstract array interface

2. There should be a specification that a type implements that
interface

3. The compiler should check that

There are many potential problems with all that:

1. Index ranges should be first-class objects with a type.
2. To implement slices one would probably need parameters/results of
anonymous array types.
3. To implement attributes one need to expose them as primitive
operations
4. To check its interface an abstract array type should be tagged,
otherwise abstract array operations will not be primitive.

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



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

* Re: The "()" operator revisited.
  2004-01-12 17:53 The "()" operator revisited Frank J. Lhota
                   ` (2 preceding siblings ...)
  2004-01-13  9:24 ` Dmitry A. Kazakov
@ 2004-01-13 13:13 ` Marin David Condic
  2004-01-13 17:38   ` Warren W. Gay VE3WWG
  3 siblings, 1 reply; 45+ messages in thread
From: Marin David Condic @ 2004-01-13 13:13 UTC (permalink / raw)


Just off the top of my head, this would probably break a lot of stuff. 
Currently operators defined with the "" are *infix* operators. The "()" 
is a Idontknowwhatkindoffix operator - and that's likely to cause all 
sorts of parser problems. The "():=" procedure is even more bizarre. Its 
part procedure call and part assignment statement. We've had numerous 
debates here about why you can't make a user defined assignment 
statement as an operator (because assignment is not defined as a 
function) and on top of that, you're creating what looks like assigning 
an expression to a procedure. I'm not sure what the consequences are of 
allowing these to have multiple indicese either - since, again, the 
original restriction on things like ">=" have always been that they were 
infix operators with binary parameters. My guess is this would have to 
make the syntax trees look like an unholy mess.

Its a noble thing to say "Ada ought to support a bunch of containers and 
it ought to do so in as natural a way as possible from the view of the 
programmer". I'm just not sure that this wouldn't break too much stuff 
to be worth it. Perhaps it would be better to invent some container 
concept and invent its own notation in some manner rather than try to 
force them to look like arrays. I'm not sure what that is, but there are 
still lots of special characters left on the keyboard and we could 
always add a few new reserved words (with some pain) - come up with a 
whole new language construct (something based Reverse Polish Notation 
maybe?) or set of constructs for dealing with containers. That might be 
easier to handle than trying to remold array notation.

MDC


Frank J. Lhota wrote:
> Last June, I proposed that in order to provide an abstract array capability,
> Ada 0y should support  user-defined "()" and "():="operators. Since this
> issue has come up again, I would like to summarize and expand on this
> proposal.
> 

-- 
======================================================================
Marin David Condic
I work for: http://www.belcan.com/
My project is: http://www.jsf.mil/NSFrames.htm

Send Replies To: m   o   d   c @ a   m   o   g
                    c   n   i       c   .   r

     "Face it ladies, its not the dress that makes you look fat.
     Its the FAT that makes you look fat."

         --  Al Bundy

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




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

* Re: The "()" operator revisited.
  2004-01-12 22:26 ` Robert A Duff
@ 2004-01-13 16:29   ` Frank J. Lhota
  0 siblings, 0 replies; 45+ messages in thread
From: Frank J. Lhota @ 2004-01-13 16:29 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wcck73w9536.fsf@shell01.TheWorld.com...
> "Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> writes:
>
> > Last June, I proposed that in order to provide an abstract array
capability,
> > Ada 0y should support  user-defined "()" and "():="operators. Since this
> > issue has come up again, I would like to summarize and expand on this
> > proposal.
>
> This is a good idea.  As you note below, it's got a long way to go
> before you've got a list of wording changes to the RM.  For example, the
> notion of operator-named *procedures* does not currently exist in Ada.

First, I'm glad you like the idea. Granted, Ada does not have operator-named
procedures, but there has been discussions about making ":=" an operator.

> But before bothering with that, I think there are some important
> issues to work out:
>
> You seem to be saying that components of arrays (or just abstract
> arrays?) are always passed by copy.  That seems like a real problem,
> since for efficiency, most compilers pass large things by reference.
> (I'm talking about the case of array-of-large-array or
> array-of-large-record.)

I did not mean to imply anything about the parameter passing convention
used. Clearly, we need to support all parameter passing conventions, since
any type can be used as an array component.

The confusion probably arose from the discussion of passing an array
component as a parameter of mode "in out". Now if the array component is
aliased, passing the component by reference is easy: simply pass the address
of the component. If the component is not aliased, as is often the case,
this method would not work. The way many compilers (including GNAT) handle
passing a packed component to a subprogram is:

- Create a temporary variable of the given component type;
- If the parameter is of mode "in" or "in out", unpack the array component
into the temporary variable;
- Pass this temporary variable to the subprogram; and
- If the parameter is of mode "out" or "in out", pack the temporary variable
value into the  array component.

Note that although this requires a temporary copy, it does NOT require that
the subprogram parameter use pass by copy.

Given that this is done currently for packed arrays, there is no good reason
why this cannot be done for the proposed abstract

> Furthermore, if the component type is limited, it is *required* to be
> passed by reference.  This raises the question: can "():=" be declared
> for limited types?

The idea of assigning a limited component to an array component is tricky,
given that there is never to be more than one copy of an object of a limited
type. We can, however, take advantage of the fact that limited objects are
always aliased, and implement such an array as a collection of access values
to the limited objects. For this to work, however, the Value parameter of
"():=" would need to be "in out" mode in order to get a non-constant
reference, so I propose that we also allow "():=" to be declared as

    procedure "():=" ( Source  : in out Abstract_Array_Type;
                       Index_1 : in     Index_Type_1;
                       Index_2 : in     Index_Type_2;
                       ...
                       Index_N : in     Index_Type_N;
                       Value   : in out Component_Type );

I have prototyped this with a limited type.

> What does A(I)'Access mean in this scheme?

Abstract array components, in general, are not aliased, so that expression
would not be legal. In some abstract arrays, however, the components would
be aliased, so we should probably allow the user to specify the access value
to be returned in such cases.

> Are there interactions with Adjust, which is normally called for
> assignment of nonlimited controlled types?

The "()" and "():=" are regular subprograms, so Adjust would be called
whenever the subprogram code requires it.

> You seem to treat 'out' parameters as copy-out only.  But for composite
> types, 'out' means pretty much the same thing as 'in out' -- at least
> *some* parts of the object are copied *in* (see RM for details).
> Likewise, if the component type is an access type, you can't allow
> undefined values to be created -- all access objects have to be
> initialized to 'null' if they aren't initialized to something else
> meaningful.

This type of initialization could easily be done before calling the
subprogram, so I don't see how this is a barrier for abstract arrays.

> You seemed to be hoping that this new notation could underly the
> definition of the *existing* array indexing semantics.  That would be
> elegant.  However, some of the above issues mean it doesn't work -- at
> least as you've defined it so far.

Is there an issue other than parameter passing?

> > Note: the following discussion probably has an insufficient amount of
> > legalese to satisfy language lawyers. Once we've thrashed out these
ideas,
> > I'll be happy to work with anyone with formalizing this proposal.
>
> I hate to be discouraging, but my guess is that a proposal like this is
> *not* going to be accepted by the ARG, even if were written up as proper
> RM wording changes.

That is quite possibly true. I have never done a submission to the ARG
before, so I'm not really up on the procedure. The first step, however, is
to have a solid idea for submission, which is why we're discussing it here.

> > Similar declarations can be added to Ada.Strings.Bounded. This would
permit
> > the higher-level Ada string types to use the same notation as the
low-level
> > standard String type.
>
> Well, it allows that for the particular notation of array indexing,
> and that would be a good thing.  But it doesn't completely solve
> the problem.  It doesn't support slice notation (but I don't think
> slices are all that important).  And it doesn't support string literal
> notation -- I think that *is* important -- it's really annoying that you
> can't have a string literal of type uunbounded string.  Similarly, it
> doesn't support aggregate notation.
>
> If I were designing a language from scratch, I would allow user-defined
> meanings for all of the above notations.  But as I said, unfortunately,
> I don't see this happening for Ada 0X.
>
> - Bob





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

* Re: The "()" operator revisited.
  2004-01-13  9:24 ` Dmitry A. Kazakov
@ 2004-01-13 16:44   ` Frank J. Lhota
  2004-01-13 17:13     ` Hyman Rosen
                       ` (3 more replies)
  0 siblings, 4 replies; 45+ messages in thread
From: Frank J. Lhota @ 2004-01-13 16:44 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:dmc700tmurmei4u19nof44803bv19f6d6o@4ax.com...
> More specifically, how would it be matched against a formal
> generic array parameter?

That is far more ambitious than this proposal. The basic idea of this
proposal is to allow array indexing notation for collections. For example,
assume that we have a hash table that maps employee names to employee
records. It would be nice if we could define "()" and "():=" for this hash
table so that we could write something like this:

    declare
       Rec : Employee_Record_Hash_Table;
    begin
       ...
       Rec( "Johnson" ) := This_Rec;
       Display( The_Rec => Rec( "Smith" ) );
       ...
    end;

To get something that could match a generic array parameter would require a
lot of restrictions on abstract arrays, in particular that the indice types
would have to be abstract discrete types. This would rule out abstract
arrays such as what we see in this example.





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

* Re: The "()" operator revisited.
  2004-01-13 16:44   ` Frank J. Lhota
@ 2004-01-13 17:13     ` Hyman Rosen
  2004-01-13 22:27     ` Randy Brukardt
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 45+ messages in thread
From: Hyman Rosen @ 2004-01-13 17:13 UTC (permalink / raw)


Frank J. Lhota wrote:
>>More specifically, how would it be matched against a formal
>>generic array parameter?
> 
> That is far more ambitious than this proposal.

You should begin to see why C++ templates don't come with a mechanism
to specify restrictions on parameters, and instead rely on seeing if
usage within the code is legal.




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

* Re: The "()" operator revisited.
  2004-01-13 13:13 ` Marin David Condic
@ 2004-01-13 17:38   ` Warren W. Gay VE3WWG
  2004-01-13 19:09     ` Robert A Duff
  0 siblings, 1 reply; 45+ messages in thread
From: Warren W. Gay VE3WWG @ 2004-01-13 17:38 UTC (permalink / raw)


Marin David Condic wrote:
> Just off the top of my head, this would probably break a lot of stuff. 
> Currently operators defined with the "" are *infix* operators. The "()" 
> is a Idontknowwhatkindoffix operator - and that's likely to cause all 
> sorts of parser problems. The "():=" procedure is even more bizarre. Its 
> part procedure call and part assignment statement. We've had numerous 
> debates here about why you can't make a user defined assignment 
> statement as an operator (because assignment is not defined as a 
> function) and ...

I am not personally convinced about the need for "()" myself, but
I often wonder about more control over assignment however.  One
example that does exist in ada is the Adjust method in a
controlled type. Not having throught this through deeply (I admit),
I still wonder if it wouldn't be useful to allow control over
the actual assignment operation in a more general way (as an
operator).

Was operator assignment ever considered for Ada? If it was, and shot
down, what were the primary reasons against it?

Just curios.

-- 
Warren W. Gay VE3WWG
http://ve3wwg.tk




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

* RE: The "()" operator revisited.
@ 2004-01-13 17:46 amado.alves
  2004-01-13 22:21 ` Randy Brukardt
  0 siblings, 1 reply; 45+ messages in thread
From: amado.alves @ 2004-01-13 17:46 UTC (permalink / raw)
  To: comp.lang.ada

<<...To get something that could match a generic array parameter would require a
lot of restrictions on abstract arrays, in particular that the indice types
would have to be abstract discrete types. This would rule out abstract
arrays such as what we see in this example.>>

Which would be unfortunate. One solution would to add abstract arrays to the set of generic parameters. This whole proposal should articulate with other proposals: user-defined ":=", implicit conversion. Also, there was already a thread on the current issue, some months ago. Implicit conversion could solve the problems of having non-discrete values for the index, and literals. All together this would be a really big change to the language and there is no way it's going to make it in Ada 2005. As someone already said, better write the language from scratch. It is a fascinating issue, but academic.

The alternative is to have abstract arrays as a severely restricted class (perhaps a subclass of arrays). Actually the original proposal so it seems. But I doubt it makes in time to Ada 2005.

In sum, I must have too much free time on my hands to be posting this, because I don't believe any currently appearing proposal is going to make it in time for Ada 2005, and I fear Ada 2005 is going to be the last Ada. With luck we'll be designing a new language, incorporating the lessons learnt from Ada 1983-2005.



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

* RE: The "()" operator revisited.
@ 2004-01-13 17:53 amado.alves
  2004-01-14  9:09 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: amado.alves @ 2004-01-13 17:53 UTC (permalink / raw)
  To: Hyman Rosen, comp.lang.ada

"You should begin to see why C++ templates don't come with a mechanism
to specify restrictions on parameters, and instead rely on seeing if
usage within the code is legal."

Right, and on Future_Language we will have the best of both worlds: any degree of restriction on the parameter definition. Currently I simulate classes outside the established set with formal packages.



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

* Re: The "()" operator revisited.
  2004-01-13 17:38   ` Warren W. Gay VE3WWG
@ 2004-01-13 19:09     ` Robert A Duff
  2004-01-15 17:30       ` Warren W. Gay VE3WWG
  0 siblings, 1 reply; 45+ messages in thread
From: Robert A Duff @ 2004-01-13 19:09 UTC (permalink / raw)


"Warren W. Gay VE3WWG" <warren@ve3wwg.tk> writes:

> Was operator assignment ever considered for Ada? If it was, and shot
> down, what were the primary reasons against it?

See AARM-7.6(17.a).

- Bob



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

* Re: The "()" operator revisited.
  2004-01-13 17:46 amado.alves
@ 2004-01-13 22:21 ` Randy Brukardt
  0 siblings, 0 replies; 45+ messages in thread
From: Randy Brukardt @ 2004-01-13 22:21 UTC (permalink / raw)


"amado.alves" <amado.alves@netcabo.pt> wrote in message
news:mailman.31.1074016060.279.comp.lang.ada@ada-france.org...
...because I don't believe any currently appearing proposal is going to make
it in time for Ada 2005,...

That's certainly true, given that the deadline for submission of proposals
from the general public was September 30th, 2003, and from insiders was
December 31st, 2003. In theory, even Tucker can't propose a new idea and get
it into Ada 200Y. (I'll believe that when I see it. :-)

In any case, we're supposed to be working to finish what we've already
started, not start working on new ideas. Of course, ideas for Ada 201Z are
welcome. :-)

           Randy Brukardt
           ARG Editor






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

* Re: The "()" operator revisited.
  2004-01-13 16:44   ` Frank J. Lhota
  2004-01-13 17:13     ` Hyman Rosen
@ 2004-01-13 22:27     ` Randy Brukardt
  2004-01-14  2:30     ` Stephen Leake
  2004-01-14  9:04     ` Dmitry A. Kazakov
  3 siblings, 0 replies; 45+ messages in thread
From: Randy Brukardt @ 2004-01-13 22:27 UTC (permalink / raw)


"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> wrote in message
news:MfVMb.11867$Qq.262@nwrdny01.gnilink.net...
>...It would be nice if we could define "()" and "():=" for this hash
> table so that we could write something like this:
>
>     declare
>        Rec : Employee_Record_Hash_Table;
>     begin
>        ...
>        Rec( "Johnson" ) := This_Rec;
>        Display( The_Rec => Rec( "Smith" ) );
>        ...
>     end;

This seems like a lot of work to eliminate a few characters. I contend that
virtually all ADTs ought to be controlled (meaning that their tagged).
Presuming that, you can use prefix notation in Ada 200Y (see AI-252). Thus,
if you have:
    function Element (Container : in Map_Type; Index : in Index_Type) return
Element_Type;
    type Element_Handle is access all Element;
    function Set (Container : in Map_Type; Index : in Index_Type) return
Element_Handle;
your example would look like:
     declare
        Rec : Employee_Record_Hash_Table;
     begin
        ...
        Rec.Set( "Johnson" ).all := This_Rec;
        Display( The_Rec => Rec.Element( "Smith" ) );
        ...
     end;

Not perfect, but quite a bit closer than we can get in Ada 95. (Of course,
if you chose short enough names, you can cut the characters used a lot
more...)

               Randy.






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

* Re: The "()" operator revisited.
  2004-01-13 16:44   ` Frank J. Lhota
  2004-01-13 17:13     ` Hyman Rosen
  2004-01-13 22:27     ` Randy Brukardt
@ 2004-01-14  2:30     ` Stephen Leake
  2004-01-14  9:04     ` Dmitry A. Kazakov
  3 siblings, 0 replies; 45+ messages in thread
From: Stephen Leake @ 2004-01-14  2:30 UTC (permalink / raw)
  To: comp.lang.ada

"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> writes:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:dmc700tmurmei4u19nof44803bv19f6d6o@4ax.com...
> > More specifically, how would it be matched against a formal
> > generic array parameter?
> 
> That is far more ambitious than this proposal. 

If I can't use it to match an array generic parameter, it's not going
to be very useful.

-- 
-- Stephe




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

* Re: The "()" operator revisited.
  2004-01-13 16:44   ` Frank J. Lhota
                       ` (2 preceding siblings ...)
  2004-01-14  2:30     ` Stephen Leake
@ 2004-01-14  9:04     ` Dmitry A. Kazakov
  2004-01-17  0:15       ` Kenneth Almquist
  3 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2004-01-14  9:04 UTC (permalink / raw)


On Tue, 13 Jan 2004 16:44:28 GMT, "Frank J. Lhota"
<NOSPAM.lhota.adarose@verizon.net> wrote:

>"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>news:dmc700tmurmei4u19nof44803bv19f6d6o@4ax.com...
>> More specifically, how would it be matched against a formal
>> generic array parameter?
>
>That is far more ambitious than this proposal.

Ada is a language with great ambitions! (:-))

> The basic idea of this
>proposal is to allow array indexing notation for collections. For example,
>assume that we have a hash table that maps employee names to employee
>records. It would be nice if we could define "()" and "():=" for this hash
>table so that we could write something like this:
>
>    declare
>       Rec : Employee_Record_Hash_Table;
>    begin
>       ...
>       Rec( "Johnson" ) := This_Rec;
>       Display( The_Rec => Rec( "Smith" ) );
>       ...
>    end;

The problem is that without notion of abstract array as a class-wide
or generic parameter type, there will be no way to write
class-wide/generic subroutines taking advantage of indexing. Let I
have all containers of different kind having () indexing. This will
not help me. Because I will still be unable as little as just to write
a universal program searching max element in *a* container.

>To get something that could match a generic array parameter would require a
>lot of restrictions on abstract arrays, in particular that the indice types
>would have to be abstract discrete types.

No. We should simply go on and introduce abstract index type as a
counterpart of the formal discrete type:

type X is (<>);

One should be consequent. We need abstract discrete, integer, index,
numeric, string, array, access types. Have I forgot something? (:-))

> This would rule out abstract
>arrays such as what we see in this example.

I am not sure that hash table is an array. But if it should be (why
not) then, we should also distinguish two different kind of index
types:

1. Ordered, dense indices. Having ".." primitive operation and so
allowing iteration of arrays built upon them.

2. Unordered indices, with no [public] order defined (or used). An
array with an unordered index would be a hash table.

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



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

* Re: The "()" operator revisited.
  2004-01-13 17:53 amado.alves
@ 2004-01-14  9:09 ` Dmitry A. Kazakov
  2004-01-14 12:55   ` Georg Bauhaus
  2004-01-14 13:04   ` Hyman Rosen
  0 siblings, 2 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2004-01-14  9:09 UTC (permalink / raw)


On Tue, 13 Jan 2004 17:53:24 -0000, "amado.alves"
<amado.alves@netcabo.pt> wrote:

>"You should begin to see why C++ templates don't come with a mechanism
>to specify restrictions on parameters, and instead rely on seeing if
>usage within the code is legal."
>
>Right, and on Future_Language we will have the best of both worlds: any degree of restriction on the parameter definition. Currently I simulate classes outside the established set with formal packages.

Wrong, the Future Language will need no templates. (:-))

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



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

* Re: The "()" operator revisited.
  2004-01-14  9:09 ` Dmitry A. Kazakov
@ 2004-01-14 12:55   ` Georg Bauhaus
  2004-01-14 15:05     ` Dmitry A. Kazakov
  2004-01-14 13:04   ` Hyman Rosen
  1 sibling, 1 reply; 45+ messages in thread
From: Georg Bauhaus @ 2004-01-14 12:55 UTC (permalink / raw)


Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
: 
: Wrong, the Future Language will need no templates. (:-))

Thus

	type Set;
	function Set.contains(e: Any) -> Boolean;
	...

	type AppleSet;
	function AppleSet.contains(e: Apple) -> Boolean;
	...

	type OrangeSet;
	function AppleSet.contains(e: Orange) -> Boolean;
	...


Or which way?


-- Georg



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

* Re: The "()" operator revisited.
  2004-01-14  9:09 ` Dmitry A. Kazakov
  2004-01-14 12:55   ` Georg Bauhaus
@ 2004-01-14 13:04   ` Hyman Rosen
  1 sibling, 0 replies; 45+ messages in thread
From: Hyman Rosen @ 2004-01-14 13:04 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> Wrong, the Future Language will need no templates. (:-))

I guess we'll each have our own version of FutLan, then :-)




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

* Re: The "()" operator revisited.
  2004-01-14 12:55   ` Georg Bauhaus
@ 2004-01-14 15:05     ` Dmitry A. Kazakov
  2004-01-15  1:21       ` Georg Bauhaus
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2004-01-14 15:05 UTC (permalink / raw)


On Wed, 14 Jan 2004 12:55:36 +0000 (UTC), Georg Bauhaus
<sb463ba@l1-hrz.uni-duisburg.de> wrote:

>Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
>: 
>: Wrong, the Future Language will need no templates. (:-))
>
>Thus
>
>	type Set;
>	function Set.contains(e: Any) -> Boolean;
>	...
>
>	type AppleSet;
>	function AppleSet.contains(e: Apple) -> Boolean;

Is AppleSet related to Set? I do not like the C++ way, of telling that
they both have a function named "contains".
>	...
>
>	type OrangeSet;
>	function AppleSet.contains(e: Orange) -> Boolean;
>	...
>
>Or which way?

Templates are for generic programming. I would like to do generic
programming in terms class-wide subroutines and discriminated types.
Then in place of template specialization, I would put constraints on
discriminants. I would also treat X'Tag as a discriminant of S'Class.
Though it would be interesting to consider making types the first
class objects, I think that we could replace them with their tags,
instead.

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



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

* RE: The "()" operator revisited.
@ 2004-01-14 15:22 amado.alves
  2004-01-14 16:16 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: amado.alves @ 2004-01-14 15:22 UTC (permalink / raw)
  To: comp.lang.ada

"Templates are for generic programming...."
 
Generics is the poor man's dynamic program construction. Ada generics are in the tradition of strong compile-time type checking. I dream of unifying strong checking with dynamic construction. Intentional programming perhaps. Maybe that can be done playing with ASIS. Anyway types as objects/values would be required I think.
 



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

* Re: The "()" operator revisited.
  2004-01-14 15:22 amado.alves
@ 2004-01-14 16:16 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2004-01-14 16:16 UTC (permalink / raw)


On Wed, 14 Jan 2004 15:22:43 -0000, "amado.alves"
<amado.alves@netcabo.pt> wrote:

>"Templates are for generic programming...."
> 
> Generics is the poor man's dynamic program construction.

Generic programming is designing programs valid for many types. This
is not necessarily dynamic. It is rather difficult to call templates
dynamic, at least in the sense of run-time, late binding.

> Ada generics are in the tradition of strong compile-time type checking.
> I dream of unifying strong checking with
> dynamic construction. Intentional programming perhaps. Maybe that can be
> done playing with ASIS. Anyway types as objects/values would be required I think.

Yes, this could be interesting. However in my view one of the problems
with generics is their power. I like to compare them with gotos. Goto,
the Great is also much more powerful than a faint IF-THEN-ELSE...

It seems that you wish to create something even more powerful than
templates. That's a wrong way, IMO. 

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



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

* Re: The "()" operator revisited.
  2004-01-14 15:05     ` Dmitry A. Kazakov
@ 2004-01-15  1:21       ` Georg Bauhaus
  2004-01-15  8:50         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: Georg Bauhaus @ 2004-01-15  1:21 UTC (permalink / raw)


Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
: 
: Templates are for generic programming. I would like to do generic
: programming in terms class-wide subroutines and discriminated types.

Hm. How do you know then that you get an Apple from some Set, and
not an Orange? Is there a run time penalty?



-- Georg



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

* Re: The "()" operator revisited.
  2004-01-15  1:21       ` Georg Bauhaus
@ 2004-01-15  8:50         ` Dmitry A. Kazakov
  2004-01-15 11:09           ` Georg Bauhaus
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2004-01-15  8:50 UTC (permalink / raw)


On Thu, 15 Jan 2004 01:21:16 +0000 (UTC), Georg Bauhaus
<sb463ba@l1-hrz.uni-duisburg.de> wrote:

>Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
>: 
>: Templates are for generic programming. I would like to do generic
>: programming in terms class-wide subroutines and discriminated types.
>
>Hm. How do you know then that you get an Apple from some Set, and
>not an Orange? Is there a run time penalty?

Which one? Templates do it at compile time anyway, so the type tags
are statically known. The issue is whether tags and tag checks could
be optimized out. This is why I do not like Ada functions, and want to
have them pure. It should be possible to *require* a function
evaluation at compile time.

However, for specialized arrays three things atually required:

1. array discriminants
2. viewing type tag as a discriminant of a class-wide
3. placing tags and discriminants separately from the object body when
known (same as with array bounds)

Having these things one could just write:

type Fruit is ...;
type Fruit_Array (Kind_Of : Tag) is
   array (...) of Fruit'Class (Kind_Of);

If you have Apples and Oranges, then:

type Apple is new Fruit with ...;
subtype Apple_Array is Fruit_Array (Apple'Tag);

type Orange is new Fruit with ...;
subtype Orange_Array is Fruit_Array (Orange'Tag);

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



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

* Re: The "()" operator revisited.
  2004-01-15  8:50         ` Dmitry A. Kazakov
@ 2004-01-15 11:09           ` Georg Bauhaus
  2004-01-15 13:23             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: Georg Bauhaus @ 2004-01-15 11:09 UTC (permalink / raw)


Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
: On Thu, 15 Jan 2004 01:21:16 +0000 (UTC), Georg Bauhaus
:>Hm. How do you know then that you get an Apple from some Set, and
:>not an Orange? Is there a run time penalty?
: 
: Which one? Templates do it at compile time anyway, so the type tags
: are statically known.

That is, if I have, in a unit
procedure generic_array_shuffle(box: Fruit_Array);

and then in another unit
declare
   A: Apple_Array;
begin generic_array_shuffle(A); end;

declare
   O: Orange_Array;
begin generic_array_shuffle(O); end;

the compiler would not be informed about component sizes when
compiling the unit containing generic_array_shuffle, right?
Will it then have to, uhm, instantiate a procedure for the two
calls above with component sizes adjusted, behind the scenes?



-- Georg



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

* Re: The "()" operator revisited.
  2004-01-15 11:09           ` Georg Bauhaus
@ 2004-01-15 13:23             ` Dmitry A. Kazakov
  2004-01-17  6:26               ` Robert I. Eachus
  0 siblings, 1 reply; 45+ messages in thread
From: Dmitry A. Kazakov @ 2004-01-15 13:23 UTC (permalink / raw)


On Thu, 15 Jan 2004 11:09:27 +0000 (UTC), Georg Bauhaus
<sb463ba@l1-hrz.uni-duisburg.de> wrote:

>Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
>: On Thu, 15 Jan 2004 01:21:16 +0000 (UTC), Georg Bauhaus
>:>Hm. How do you know then that you get an Apple from some Set, and
>:>not an Orange? Is there a run time penalty?
>: 
>: Which one? Templates do it at compile time anyway, so the type tags
>: are statically known.
>
>That is, if I have, in a unit
>procedure generic_array_shuffle(box: Fruit_Array);

No, a "generic" shuffle should be:

procedure generic_array_shuffle(box: Fruit_Array'Class);

>and then in another unit
>declare
>   A: Apple_Array;
>begin generic_array_shuffle(A); end;
>
>declare
>   O: Orange_Array;
>begin generic_array_shuffle(O); end;
>
>the compiler would not be informed about component sizes when
>compiling the unit containing generic_array_shuffle, right?
>Will it then have to, uhm, instantiate a procedure for the two
>calls above with component sizes adjusted, behind the scenes?

Maybe. In your example generic_array_shuffle might be inherited or
overridden. In which case the compiler could take an advantage of
knowing the constraint. Then, the procedure could be inlined, so again
the compiler could re-instantiate its body. Presently optimizations of
this kind are not required. I would define some of them in RM to make
them mandatory.

Futher, if neither applied, what would be a penalty as compared with a
variant based on a generic procedure, which instances are reusing the
body? Actually in the static case, either the constraints have to
propagate into the body, making its reuse impossible, or not. Whether
the body itself is a template or a class-wide is of little matter.

BTW, as Knuth said: "We should forget about small efficiencies, say
about 97% of the time: premature optimization is the root of all
evil." What is the real weight of possible penalties of this kind in a
software project of a real size and application field? I have no
figures, but I suppose it is vanishingly small.

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



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

* Re: The "()" operator revisited.
  2004-01-13 19:09     ` Robert A Duff
@ 2004-01-15 17:30       ` Warren W. Gay VE3WWG
  2004-01-15 18:11         ` Robert A Duff
  0 siblings, 1 reply; 45+ messages in thread
From: Warren W. Gay VE3WWG @ 2004-01-15 17:30 UTC (permalink / raw)


Robert A Duff wrote:
> "Warren W. Gay VE3WWG" <warren@ve3wwg.tk> writes:
>>Was operator assignment ever considered for Ada? If it was, and shot
>>down, what were the primary reasons against it?
> 
> See AARM-7.6(17.a).
> 
> - Bob

I looked at this, but this doesn't really address the question.
This info talks about controlled types, adjust etc. and what
it should or shouldn't do, implementation details etc.

Perhaps I need to rephrase the question: If C++ proponents
thought it necessary (or useful) to include an assignment
operator, why was it that the Ada language (Ada83) was
developed without one? Can anyone answer this or point back
to early Ada discussions about this?

-- 
Warren W. Gay VE3WWG
http://ve3wwg.tk




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

* Re: The "()" operator revisited.
  2004-01-15 17:30       ` Warren W. Gay VE3WWG
@ 2004-01-15 18:11         ` Robert A Duff
  2004-01-15 19:36           ` tmoran
                             ` (3 more replies)
  0 siblings, 4 replies; 45+ messages in thread
From: Robert A Duff @ 2004-01-15 18:11 UTC (permalink / raw)


"Warren W. Gay VE3WWG" <warren@ve3wwg.tk> writes:

> Robert A Duff wrote:
> > "Warren W. Gay VE3WWG" <warren@ve3wwg.tk> writes:
> >>Was operator assignment ever considered for Ada? If it was, and shot
> >>down, what were the primary reasons against it?
> > See AARM-7.6(17.a).
> > - Bob
> 
> I looked at this, but this doesn't really address the question.
> This info talks about controlled types, adjust etc. and what
> it should or shouldn't do, implementation details etc.
> 
> Perhaps I need to rephrase the question: If C++ proponents
> thought it necessary (or useful) to include an assignment
> operator, why was it that the Ada language (Ada83) was
> developed without one? Can anyone answer this or point back
> to early Ada discussions about this?

Sorry, I didn't realize you were talking about Ada 83.  Why can't the
user redefine ":=" in Ada 83?  I don't know, but I guess the designers
didn't like users redefining stuff like that.  Same reason the user
can't redefine "in" or aggregate notation or literal notation or array
indexing notation, I guess.  It seems inconsistent with the fact that
you *can* redefine "=" and "+" and so forth.

In Ada 9X, we decided the user *should* be able to redefine the behavior
of ":=".  AARM-7.6(17.a) explains why we didn't do that in the "obvious"
way -- some sort of syntax like:

    procedure ":="(...);

which would correspond directly to the way C++ does it.
It has to do with mutable record types (defaulted discrims).
That's unfortunate; if you want to redefine ":=" for a non-mutable
type, it's pretty annoying to be told you can't do that because
mutable types exist in the language.

The C++ way has some advantages over the Ada way (where the user's
control is split between Finalize and Adjust) because it's sometimes
convenient to get your hands on both sides of the assignment at the same
time.

- Bob



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

* Re: The "()" operator revisited.
  2004-01-15 18:11         ` Robert A Duff
@ 2004-01-15 19:36           ` tmoran
  2004-01-15 20:35             ` Robert A Duff
  2004-01-16  1:52           ` Redefining := (was: The "()" operator revisited.) Jeffrey Carter
                             ` (2 subsequent siblings)
  3 siblings, 1 reply; 45+ messages in thread
From: tmoran @ 2004-01-15 19:36 UTC (permalink / raw)


>control is split between Finalize and Adjust) because it's sometimes
>convenient to get your hands on both sides of the assignment at the same
>time.
  More than with a Self pointer available to Adjust?



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

* Re: The "()" operator revisited.
  2004-01-15 19:36           ` tmoran
@ 2004-01-15 20:35             ` Robert A Duff
  2004-01-17  5:48               ` Robert I. Eachus
  0 siblings, 1 reply; 45+ messages in thread
From: Robert A Duff @ 2004-01-15 20:35 UTC (permalink / raw)


tmoran@acm.org writes:

> >control is split between Finalize and Adjust) because it's sometimes
> >convenient to get your hands on both sides of the assignment at the same
> >time.
>   More than with a Self pointer available to Adjust?

I'm not sure what you mean by that.

Adjust gets control after the (old) left-hand side has been finalized.
So, for example, how could ":=" reuse the space of the LHS?
Also, what if you want the whole ":=" to be locked, rather than
just part of it?

- Bob



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

* Redefining := (was: The "()" operator revisited.)
  2004-01-15 18:11         ` Robert A Duff
  2004-01-15 19:36           ` tmoran
@ 2004-01-16  1:52           ` Jeffrey Carter
  2004-01-16 21:37             ` Randy Brukardt
  2004-01-16  3:11           ` The "()" operator revisited Mark A. Biggar
  2004-01-16 13:56           ` Frank J. Lhota
  3 siblings, 1 reply; 45+ messages in thread
From: Jeffrey Carter @ 2004-01-16  1:52 UTC (permalink / raw)


Robert A Duff wrote:

> It has to do with mutable record types (defaulted discrims).
> That's unfortunate; if you want to redefine ":=" for a non-mutable
> type, it's pretty annoying to be told you can't do that because
> mutable types exist in the language.

Could you do something like:

type Mutable (D : Natural := 0) is record
    ... -- whatever
end record;

type M2 is new Mutable;

procedure ":=" (To : out Mutable; From : in Mutable) is
    Result : M2 (D => From.D);

    procedure Assign (To : out M2; From : in M2) is
    begin -- Assign
       To := From;
       -- You can use default ":=" with M2 because it hasn't been
       -- redefined
    end Assign;
begin -- ":="
    -- Mess around with Result until it has what you want
    Assign (To => M2 (To), From => Result);
end ":=";

?

-- 
Jeff Carter
"I wave my private parts at your aunties."
Monty Python & the Holy Grail
13




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

* Re: The "()" operator revisited.
  2004-01-15 18:11         ` Robert A Duff
  2004-01-15 19:36           ` tmoran
  2004-01-16  1:52           ` Redefining := (was: The "()" operator revisited.) Jeffrey Carter
@ 2004-01-16  3:11           ` Mark A. Biggar
  2004-01-16 13:28             ` Hyman Rosen
                               ` (2 more replies)
  2004-01-16 13:56           ` Frank J. Lhota
  3 siblings, 3 replies; 45+ messages in thread
From: Mark A. Biggar @ 2004-01-16  3:11 UTC (permalink / raw)


Robert A Duff wrote:

> "Warren W. Gay VE3WWG" <warren@ve3wwg.tk> writes:
> 
> 
>>Robert A Duff wrote:
>>
>>>"Warren W. Gay VE3WWG" <warren@ve3wwg.tk> writes:
>>>
>>>>Was operator assignment ever considered for Ada? If it was, and shot
>>>>down, what were the primary reasons against it?
>>>
>>>See AARM-7.6(17.a).
>>>- Bob
>>
>>I looked at this, but this doesn't really address the question.
>>This info talks about controlled types, adjust etc. and what
>>it should or shouldn't do, implementation details etc.
>>
>>Perhaps I need to rephrase the question: If C++ proponents
>>thought it necessary (or useful) to include an assignment
>>operator, why was it that the Ada language (Ada83) was
>>developed without one? Can anyone answer this or point back
>>to early Ada discussions about this?
> 
> 
> Sorry, I didn't realize you were talking about Ada 83.  Why can't the
> user redefine ":=" in Ada 83?  I don't know, but I guess the designers
> didn't like users redefining stuff like that.  Same reason the user
> can't redefine "in" or aggregate notation or literal notation or array
> indexing notation, I guess.  It seems inconsistent with the fact that
> you *can* redefine "=" and "+" and so forth.
> 
> In Ada 9X, we decided the user *should* be able to redefine the behavior
> of ":=".  AARM-7.6(17.a) explains why we didn't do that in the "obvious"
> way -- some sort of syntax like:
> 
>     procedure ":="(...);
> 
> which would correspond directly to the way C++ does it.
> It has to do with mutable record types (defaulted discrims).
> That's unfortunate; if you want to redefine ":=" for a non-mutable
> type, it's pretty annoying to be told you can't do that because
> mutable types exist in the language.
> 
> The C++ way has some advantages over the Ada way (where the user's
> control is split between Finalize and Adjust) because it's sometimes
> convenient to get your hands on both sides of the assignment at the same
> time.

There are other issues as well.  Ada has several things that look like
assigmment but are subtly different: Variable initialization, function 
return, by-value parameter binding, etc.  It was decided that allowing
a user to redefine assignment piecewise (initialize, adjust, finalize)
would allow the compiler to compose the various assignment like 
operations out of those pieces and other things like bit-wise memory
copy without requiring the user to define all those different variants.

-- 
mark@biggar.org
mark.a.biggar@comcast.net




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

* Re: The "()" operator revisited.
  2004-01-16  3:11           ` The "()" operator revisited Mark A. Biggar
@ 2004-01-16 13:28             ` Hyman Rosen
  2004-01-16 16:19             ` Robert A Duff
  2004-01-16 18:09             ` Warren W. Gay VE3WWG
  2 siblings, 0 replies; 45+ messages in thread
From: Hyman Rosen @ 2004-01-16 13:28 UTC (permalink / raw)


Mark A. Biggar wrote:
 > Ada has several things that look like
> assigmment but are subtly different

C++ uses two operations to handle things like that.
One is assignment, where an existing object has its value replaced by a new value,
The other is copy construction, where a new object is initialized from an existing one.
In both cases, the source and destination objects are available to the methods.




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

* Re: The "()" operator revisited.
  2004-01-15 18:11         ` Robert A Duff
                             ` (2 preceding siblings ...)
  2004-01-16  3:11           ` The "()" operator revisited Mark A. Biggar
@ 2004-01-16 13:56           ` Frank J. Lhota
  2004-01-16 16:14             ` Robert A Duff
  3 siblings, 1 reply; 45+ messages in thread
From: Frank J. Lhota @ 2004-01-16 13:56 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wcczncpgjzv.fsf@shell01.TheWorld.com...
> The C++ way has some advantages over the Ada way (where the user's
> control is split between Finalize and Adjust) because it's sometimes
> convenient to get your hands on both sides of the assignment at the same
> time.

You can get access to both sides of an assignment in Ada 95, using a variant
of the Rosen trick. The idea is to add a component to the controlled object
that holds an access value for the object itself, e.g.

   type My_Controlled_Access is access all My_Controlled_Type;

   type My_Controlled_Type is new Ada.Finalization.Controlled with
      record
         Self : My_Controlled_Access;    -- Always accesses the containing
object.
         ...
      end record;

   procedure Initialize(Object : in out My_Controlled_Type) is
   begin
      Object.Self := Object'Access;
      ...
   end Initialize;

Now when Adjust is called, the object will be a bit copy of the right hand
side of the assignment. In particular, this gives you a component with an
access value for the right hand side. In Adjust, we can simply save the
value of this component, and reset it to access the left hand of the
assignment (i.e. the current object). Now we have access to both sides of
the assignment, e.g.

   procedure Adjust(Object : in out My_Controlled_Type) is
      Right_Hand_Side : constant My_Controlled_Access := Object.Self;
   begin
      Object.Self := Object'Access;
      -- Now the left hand side of the assignment is in Object,
      -- and the Right Hand side is in the saved value of Object.Self.
      ...
   end Adjust;

Note that although the Rosen trick works, it is, after all, still a trick. I
agree that there are probably cases where it would be nice to be able to
define the ":=" operator in Ada. As someone who has coded in both Ada and
C++, I must however admit that in most cases I have found the Initialize /
Adjust / Finalize coding to be easier than doing the C++ equivalents.





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

* Re: The "()" operator revisited.
  2004-01-16 13:56           ` Frank J. Lhota
@ 2004-01-16 16:14             ` Robert A Duff
  2004-01-16 21:29               ` Frank J. Lhota
  0 siblings, 1 reply; 45+ messages in thread
From: Robert A Duff @ 2004-01-16 16:14 UTC (permalink / raw)


"Frank J. Lhota" <NOSPAM.lhota.adarose@verizon.net> writes:

> You can get access to both sides of an assignment in Ada 95, using a variant
> of the Rosen trick.

I don't see how this trick can work.  By the time Adjust gets called,
the (old) value of the lhs has been destroyed.

Suppose you have a controlled type containing a pointer to
heap-allocated data.  You want ":=" to copy the data.
But if the lhs happens to be the right size, you want to reuse that space,
rather than deallocating it and allocating a new heap object.
I don't know how to do that in Ada, and I don't see how the trick
below helps.

>... The idea is to add a component to the controlled object
> that holds an access value for the object itself, e.g.
> 
>    type My_Controlled_Access is access all My_Controlled_Type;
> 
>    type My_Controlled_Type is new Ada.Finalization.Controlled with
>       record
>          Self : My_Controlled_Access;    -- Always accesses the containing
> object.
>          ...
>       end record;
> 
>    procedure Initialize(Object : in out My_Controlled_Type) is
>    begin
>       Object.Self := Object'Access;

That's illegal; you need 'Unchecked_Access.

- Bob



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

* Re: The "()" operator revisited.
  2004-01-16  3:11           ` The "()" operator revisited Mark A. Biggar
  2004-01-16 13:28             ` Hyman Rosen
@ 2004-01-16 16:19             ` Robert A Duff
  2004-01-16 18:09             ` Warren W. Gay VE3WWG
  2 siblings, 0 replies; 45+ messages in thread
From: Robert A Duff @ 2004-01-16 16:19 UTC (permalink / raw)


"Mark A. Biggar" <mark@biggar.org> writes:

> There are other issues as well.  Ada has several things that look like
> assigmment but are subtly different: Variable initialization, function
> return, by-value parameter binding, etc.

This is true, but there are really only *two* things that look like ":="
-- the assignment_statement, and initialization of a newly-created
object.  Everything besides assignment_statement falls into the latter
category.

- Bob



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

* Re: The "()" operator revisited.
  2004-01-16  3:11           ` The "()" operator revisited Mark A. Biggar
  2004-01-16 13:28             ` Hyman Rosen
  2004-01-16 16:19             ` Robert A Duff
@ 2004-01-16 18:09             ` Warren W. Gay VE3WWG
  2 siblings, 0 replies; 45+ messages in thread
From: Warren W. Gay VE3WWG @ 2004-01-16 18:09 UTC (permalink / raw)


Mark A. Biggar wrote:
> Robert A Duff wrote:
>> "Warren W. Gay VE3WWG" <warren@ve3wwg.tk> writes:
>>> Robert A Duff wrote:
>>>> "Warren W. Gay VE3WWG" <warren@ve3wwg.tk> writes:
>>>>
>>>>> Was operator assignment ever considered for Ada? If it was, and shot
>>>>> down, what were the primary reasons against it?
>>>>
>>>> See AARM-7.6(17.a).
>>>> - Bob
>>>
...
>> Sorry, I didn't realize you were talking about Ada 83.  Why can't the
>> user redefine ":=" in Ada 83?  I don't know, but I guess the designers
>> didn't like users redefining stuff like that.  Same reason the user
>> can't redefine "in" or aggregate notation or literal notation or array
>> indexing notation, I guess.  It seems inconsistent with the fact that
>> you *can* redefine "=" and "+" and so forth.
...
>> The C++ way has some advantages over the Ada way (where the user's
>> control is split between Finalize and Adjust) because it's sometimes
>> convenient to get your hands on both sides of the assignment at the same
>> time.
> 
> There are other issues as well.  Ada has several things that look like
> assigmment but are subtly different: Variable initialization, function 
> return, by-value parameter binding, etc.  It was decided that allowing
> a user to redefine assignment piecewise (initialize, adjust, finalize)
> would allow the compiler to compose the various assignment like 
> operations out of those pieces and other things like bit-wise memory
> copy without requiring the user to define all those different variants.

OK, I am beginning to see where the issues lie. I suppose one
extreme example involves variant records, where the size of the
variant must be known in advance. A strict bit-by-bit copy followed
by tweaking makes perfect sense to me in this scenario. Although,
I suppose an implementation could assign maximum storage and
potentially resize the object after the ":=" procedure was done.

But it looks like there are some other issues involved in Ada that
don't come up in a C++ context. Thanks for the explanations.

Warren.

-- 
Warren W. Gay VE3WWG
http://ve3wwg.tk




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

* Re: The "()" operator revisited.
  2004-01-16 16:14             ` Robert A Duff
@ 2004-01-16 21:29               ` Frank J. Lhota
  0 siblings, 0 replies; 45+ messages in thread
From: Frank J. Lhota @ 2004-01-16 21:29 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wccsmifj2fa.fsf@shell01.TheWorld.com...
> I don't see how this trick can work.  By the time Adjust gets called,
> the (old) value of the lhs has been destroyed.

It depends on what you want to do. It doe make the RHS object available to
Adjust. If you need the old value of the LHS at this point, then this
approach will not work. By the time Adjust has been called, the old LHS
value has been finalized and overwritten.






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

* Re: Redefining := (was: The "()" operator revisited.)
  2004-01-16  1:52           ` Redefining := (was: The "()" operator revisited.) Jeffrey Carter
@ 2004-01-16 21:37             ` Randy Brukardt
  2004-01-19 11:33               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 45+ messages in thread
From: Randy Brukardt @ 2004-01-16 21:37 UTC (permalink / raw)


"Jeffrey Carter" <spam@spam.com> wrote in message
news:ltHNb.11315$1e.3373@newsread2.news.pas.earthlink.net...
> Robert A Duff wrote:
>
> > It has to do with mutable record types (defaulted discrims).
> > That's unfortunate; if you want to redefine ":=" for a non-mutable
> > type, it's pretty annoying to be told you can't do that because
> > mutable types exist in the language.

Bob's comment is a bit misleading. The problem is that since mutable types
exist in the language, you can't redefine ":=" for any types. That occurs
because of composition issues. You want user-defined ":=" to compose, such
that a larger type containing a component of a type using user-defined ":="
uses the user-defined ":=". Now, consider:

     type Something ...
     procedure ":=" (Target : out Something; Source : in Something);

     type Mutable (B : Boolean := False) is record
          case B is
                  when True =>
                          S : Something;
                  when False =>
                          C : Character;
          end case;
    end record;

    A_True : Mutable(True);
    A_False : Mutable(False);

    Obj : Mutable;

    Obj := A_True; -- ??

How does the predefined ":=" for Mutable work? It needs to call the
user-defined ":=" for component S. But in this example, what do you pass for
the LHS? It doesn't have a component S!

In order to deal with this, you pretty much have to separate the
finalization and initialization steps. Which is where the current model
comes from.

An alternative would be to require the ":=" to be overridden for Mutable.
But how would the user write that operation? They'd have to have made
finalization and initialization operations visible for Something, or it
isn't possible. And it seems to eliminate much of the advantage of allowing
user-defined versions of these operations (which is automatic composition).
(And the requirement probably would be a generic contract model problem. But
that's the least of the problems here.)

As Bob says, there are things you can't do with Adjust that you'd like to.
(It was described as a 75% solution when it was introduced. But our choices
were 75% or nothing, given the DRs opposition to anything fancier.) It's
hard to imagine doing much better without a lot of incompatibility (you
couldn't add a ":=" to an existing type without possibly breaking many uses
of the type) and a lot of work.

                   Randy.






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

* Re: The "()" operator revisited.
  2004-01-14  9:04     ` Dmitry A. Kazakov
@ 2004-01-17  0:15       ` Kenneth Almquist
  2004-01-17 21:15         ` Robert A Duff
  2004-01-19 10:25         ` Dmitry A. Kazakov
  0 siblings, 2 replies; 45+ messages in thread
From: Kenneth Almquist @ 2004-01-17  0:15 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> The problem is that without notion of abstract array as a class-wide
> or generic parameter type, there will be no way to write
> class-wide/generic subroutines taking advantage of indexing. Let I
> have all containers of different kind having () indexing. This will
> not help me. Because I will still be unable as little as just to write
> a universal program searching max element in *a* container.

You can write it.  The problem is that it's awkward to instantiate.

    generic
        type Collection is limited private;
        type Index is (<>);
        type Element is private;
        with function "()"(C : Collection; I : Index) return Element is <>;
        with function First(C : Collection) return Index is <>;
        with function Last(C : Collection) return Index is <>;
        with function ">"(Left, Right : Element) return Boolean is <>;
        Element_First : Element;   -- Value of Element'first
    function Max(C : Collection) return Element;

    function Max(C : Collection) return Element is
        Result : Element := First;
    begin
        for I in First(C) .. Last(C) loop
            if C(I) > Result then
                Result := C(I);
            end if;
        end loop;
        return Result;
    end Max;

>> To get something that could match a generic array parameter would require
>> a lot of restrictions on abstract arrays, in particular that the indice
>> types would have to be abstract discrete types.
>
> No. We should simply go on and introduce abstract index type as a
> counterpart of the formal discrete type:
>
> type X is (<>);
>
> One should be consequent. We need abstract discrete, integer, index,
> numeric, string, array, access types. Have I forgot something? (:-))

The problem with extending the Ada class system to cover user
defined types is that the language specification is never going
to include all the classes that user defined types might fall
into.  Languages like Haskell get around this by allowing the
programmer to define new classes.

Ada already has a work-around for the lack of user-defined classes:
default values for generic subprogram parameters.  I that that the
way to support user defined types which act like arrays is to
(1) make array indexing be an operator, as was proposed at the start
of this thread, (2) allow user defined types to have attributes such
as 'first and 'last, and (3) allow the generic to specify that it's
parameters must support specific attributes.  I'd also define
attributes for array types which give the index and component types,
and allow generic type parameters to have defaults.  With these
changes, the Max generic becomes:

    generic
        type Collection is limited private;
        type Index is (<>) := Collection'Index_Type;
        type Element is private := Collection'Element_Type;
        with function "()"(C : Collection; I : Index) return Element is <>;
        with Collection'Object'First;
        with Collection'Object'Last;
        with function ">"(Left, Right : Element) return Boolean is <>;
        with Element'First;
    function Max(C : Collection) return Element;

The directive "wtih Element'First;" means that type Element provides
the 'First attribute.  The directive "with Collection'Object'First;"
means that objects of type Collection provide the 'First attribute.
With these changes, the function Max can be sensibly instantiated
by providing a single parameter specifying an array type.
				Kenneth Almquist



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

* Re: The "()" operator revisited.
  2004-01-15 20:35             ` Robert A Duff
@ 2004-01-17  5:48               ` Robert I. Eachus
  0 siblings, 0 replies; 45+ messages in thread
From: Robert I. Eachus @ 2004-01-17  5:48 UTC (permalink / raw)


Robert A Duff wrote:

> Adjust gets control after the (old) left-hand side has been finalized.
> So, for example, how could ":=" reuse the space of the LHS?
> Also, what if you want the whole ":=" to be locked, rather than
> just part of it?

I have created types where exactly this locking is needed, and it is a 
royal pain. ;-)  The problem is not the calls to Adjust, it is that you 
can't be sure that a Finalize will have a matching Adjust call.  In 
particular you may have two Finalize calls per Adjust.  You end up 
keeping a stack of "unmatched" Finalize calls and using some heuristic 
to clean up.  I used an internal sequence number assigned by Initialize, 
and the address.  The lock on an address was started by a Finalize, and 
cleared by an Adjust.  All locks though had a timeout, or more actually, 
attempting to do a second Finalize of the same address resulted in a 
delay, not a busy wait.

It worked, but it felt kludgy.  I really wished we had four operations, 
one for the Finalize of the LHS, and another Finalize for all other cases.

-- 
                                           Robert I. Eachus

"The war on terror is a different kind of war, waged capture by capture, 
cell by cell, and victory by victory. Our security is assured by our 
perseverance and by our sure belief in the success of liberty." -- 
George W. Bush




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

* Re: The "()" operator revisited.
  2004-01-15 13:23             ` Dmitry A. Kazakov
@ 2004-01-17  6:26               ` Robert I. Eachus
  0 siblings, 0 replies; 45+ messages in thread
From: Robert I. Eachus @ 2004-01-17  6:26 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> Maybe. In your example generic_array_shuffle might be inherited or
> overridden. In which case the compiler could take an advantage of
> knowing the constraint. Then, the procedure could be inlined, so again
> the compiler could re-instantiate its body. Presently optimizations of
> this kind are not required. I would define some of them in RM to make
> them mandatory.
> 
> Futher, if neither applied, what would be a penalty as compared with a
> variant based on a generic procedure, which instances are reusing the
> body? Actually in the static case, either the constraints have to
> propagate into the body, making its reuse impossible, or not. Whether
> the body itself is a template or a class-wide is of little matter.

Rather than addressing what you said, let me describe how generics 
actually work in Ada.  There are four times when actuals are bound to 
formals, when the generic is compiled, when the generic instantiation is 
compiled (and notice that these first two can happen in any order), when 
the generic instantiation is elaborated at run-time, and when a generic 
subprogram, or a subprogram declared in a generic package is called.

The case that most people forget is the third one, instantiation happens 
at run-time, but before any calls.  In particular the "is <>;" construct 
is pretty weird, see 12.6(15). The matching rule says to do the matching 
at the place of the instantiation, and means it.  But as you can see 
above, instantiation occurs at run-time.  It turns out that you can 
determine at compile time which textual subprogram declaration will 
match an "is <>;" by looking at static closures, but the actual instance 
of that declaration will be determined at run-time.  In other words you 
know which textual declaration will match, but the actual match may be 
to one of the instances of this subprogram in the upward closure of the 
point of instantiation.   A fancy way of saying that the binding occurs 
at run-time, and may require passing a context.

But what you normally have to treat as determined at run-time are the 
constraints.  If the elaboration of a generic involves evaluating 
constraints, each time the instantiation is elaborated the constraints 
may be different from the time before.  You can use nested generics to 
cause "freezing" of constraint values at different points.  It all 
sounds very hard, but in practice it is easy.

-- 
                                           Robert I. Eachus

"The war on terror is a different kind of war, waged capture by capture, 
cell by cell, and victory by victory. Our security is assured by our 
perseverance and by our sure belief in the success of liberty." -- 
George W. Bush




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

* Re: The "()" operator revisited.
  2004-01-17  0:15       ` Kenneth Almquist
@ 2004-01-17 21:15         ` Robert A Duff
  2004-01-19 10:25         ` Dmitry A. Kazakov
  1 sibling, 0 replies; 45+ messages in thread
From: Robert A Duff @ 2004-01-17 21:15 UTC (permalink / raw)


ka@sorry.no.email (Kenneth Almquist) writes:

> Ada already has a work-around for the lack of user-defined classes:
> default values for generic subprogram parameters.  I that that the
> way to support user defined types which act like arrays is to
> (1) make array indexing be an operator, as was proposed at the start
> of this thread, (2) allow user defined types to have attributes such
> as 'first and 'last, and (3) allow the generic to specify that it's
> parameters must support specific attributes.

But isn't that too low level?  I mean, array-indexing syntax makes sense
for a hash table mapping strings to integers.  So I should be allowed to
say:

    if Table["begin"] = 123 then...

To calculate Max, I don't want 'First and 'Last -- I want a "for each"
method.

- Bob



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

* Re: The "()" operator revisited.
  2004-01-17  0:15       ` Kenneth Almquist
  2004-01-17 21:15         ` Robert A Duff
@ 2004-01-19 10:25         ` Dmitry A. Kazakov
  1 sibling, 0 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2004-01-19 10:25 UTC (permalink / raw)


On 16 Jan 2004 19:15:40 -0500, ka@sorry.no.email (Kenneth Almquist)
wrote:

>Dmitry A. Kazakov wrote:
>> The problem is that without notion of abstract array as a class-wide
>> or generic parameter type, there will be no way to write
>> class-wide/generic subroutines taking advantage of indexing. Let I
>> have all containers of different kind having () indexing. This will
>> not help me. Because I will still be unable as little as just to write
>> a universal program searching max element in *a* container.
>
>You can write it.  The problem is that it's awkward to instantiate.
>
>    generic
>        type Collection is limited private;
>        type Index is (<>);
>        type Element is private;
>        with function "()"(C : Collection; I : Index) return Element is <>;
>        with function First(C : Collection) return Index is <>;
>        with function Last(C : Collection) return Index is <>;
>        with function ">"(Left, Right : Element) return Boolean is <>;
>        Element_First : Element;   -- Value of Element'first
>    function Max(C : Collection) return Element;

It is not an abstract array, it is an explicit specification of some
arbitrary interface. It is awkward because array interface is not a
simple thing. But what is worse, there is no way to ensure that thing
being designed is an array until an attempt to instantiate Max with
it. So your example just illustrates the starting point:

to have ()-operator /= to have abstract array

>    function Max(C : Collection) return Element is
>        Result : Element := First;
>    begin
>        for I in First(C) .. Last(C) loop
>            if C(I) > Result then
>                Result := C(I);
>            end if;
>        end loop;
>        return Result;
>    end Max;
>
>>> To get something that could match a generic array parameter would require
>>> a lot of restrictions on abstract arrays, in particular that the indice
>>> types would have to be abstract discrete types.
>>
>> No. We should simply go on and introduce abstract index type as a
>> counterpart of the formal discrete type:
>>
>> type X is (<>);
>>
>> One should be consequent. We need abstract discrete, integer, index,
>> numeric, string, array, access types. Have I forgot something? (:-))
>
>The problem with extending the Ada class system to cover user
>defined types is that the language specification is never going
>to include all the classes that user defined types might fall
>into.

Are you talking about classes in the sense of 'Class or generic formal
parameter classes?

My position, many disagree with, is that 'Class could suffice if all
types would have it + MI [at least in the form of abstract
interfaces.]

>Languages like Haskell get around this by allowing the
>programmer to define new classes.
>
>Ada already has a work-around for the lack of user-defined classes:
>default values for generic subprogram parameters.

Ada also have a direct and better way to specify interface conformity:

generic
   type Implementation is new Interface with private;

The problem is that this is for tagged types only.

>I that that the
>way to support user defined types which act like arrays is to
>(1) make array indexing be an operator, as was proposed at the start
>of this thread, (2) allow user defined types to have attributes such
>as 'first and 'last, and (3) allow the generic to specify that it's
>parameters must support specific attributes.  I'd also define
>attributes for array types which give the index and component types,
>and allow generic type parameters to have defaults.  With these
>changes, the Max generic becomes:
>
>    generic
>        type Collection is limited private;
>        type Index is (<>) := Collection'Index_Type;

You need no explicit Index if there is an attribute for that. Actually
Index is "renaming":

subtype Index is Collection'Index_Type;

>        type Element is private := Collection'Element_Type;
>        with function "()"(C : Collection; I : Index) return Element is <>;
>        with Collection'Object'First;

Attributes should be [primitive] operations as any other, so

with function 'First (C : Collection)
   return Collection'Index_Type is <>;

>        with Collection'Object'Last;
>        with function ">"(Left, Right : Element) return Boolean is <>;
>        with Element'First;

Unfortunately this does not tell what is the type of the result. Let
Element be an array? This is why abstract interfaces are needed. To
write Max one should *require* that Element is an ordered type having
the minimal value [ to be precise, Max can be written without
Element'First ] which differs from having Element with operations
having good-looking names and profiles.

>    function Max(C : Collection) return Element;
>
>The directive "wtih Element'First;" means that type Element provides
>the 'First attribute.  The directive "with Collection'Object'First;"
>means that objects of type Collection provide the 'First attribute.
>With these changes, the function Max can be sensibly instantiated
>by providing a single parameter specifying an array type.

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



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

* Re: Redefining := (was: The "()" operator revisited.)
  2004-01-16 21:37             ` Randy Brukardt
@ 2004-01-19 11:33               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 45+ messages in thread
From: Dmitry A. Kazakov @ 2004-01-19 11:33 UTC (permalink / raw)


On Fri, 16 Jan 2004 15:37:27 -0600, "Randy Brukardt"
<randy@rrsoftware.com> wrote:

>"Jeffrey Carter" <spam@spam.com> wrote in message
>news:ltHNb.11315$1e.3373@newsread2.news.pas.earthlink.net...
>> Robert A Duff wrote:
>>
>> > It has to do with mutable record types (defaulted discrims).
>> > That's unfortunate; if you want to redefine ":=" for a non-mutable
>> > type, it's pretty annoying to be told you can't do that because
>> > mutable types exist in the language.
>
>Bob's comment is a bit misleading. The problem is that since mutable types
>exist in the language, you can't redefine ":=" for any types. That occurs
>because of composition issues. You want user-defined ":=" to compose, such
>that a larger type containing a component of a type using user-defined ":="
>uses the user-defined ":=". Now, consider:
>
>     type Something ...
>     procedure ":=" (Target : out Something; Source : in Something);
>
>     type Mutable (B : Boolean := False) is record
>          case B is
>                  when True =>
>                          S : Something;
>                  when False =>
>                          C : Character;
>          end case;
>    end record;
>
>    A_True : Mutable(True);
>    A_False : Mutable(False);
>
>    Obj : Mutable;
>
>    Obj := A_True; -- ??
>
>How does the predefined ":=" for Mutable work? It needs to call the
>user-defined ":=" for component S. But in this example, what do you pass for
>the LHS? It doesn't have a component S!

Of course, Mutable.":=" is kind of "multiple dispatching". There are
four variants of it:

case LHS.B is
   when True =>
      case RHS.B is
         when True =>
            call to ":=" on Something;
         when False =>
            finalize Character;
            call copy-constructor on Something
      end case;
   when False =>
      case RHS.B is
         when True =>
            finalize Something;
            call copy-constructor on Character
         when False =>
            call to ":=" on Character;
      end case;
end case;

Provided we had proper constructors of course! (:-))

Assignment can always be consistently generated out of assignments of
components and destructors/copy-constructors. The reverse is wrong, as
your example clearly shows. Even more obvious example:

X : constant Something := Initial;
   -- should the user-defined ":=" be called here? (:-))
   -- If, yes then what would be LHS?

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



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

end of thread, other threads:[~2004-01-19 11:33 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-01-12 17:53 The "()" operator revisited Frank J. Lhota
2004-01-12 18:38 ` Frank J. Lhota
2004-01-12 22:26 ` Robert A Duff
2004-01-13 16:29   ` Frank J. Lhota
2004-01-13  9:24 ` Dmitry A. Kazakov
2004-01-13 16:44   ` Frank J. Lhota
2004-01-13 17:13     ` Hyman Rosen
2004-01-13 22:27     ` Randy Brukardt
2004-01-14  2:30     ` Stephen Leake
2004-01-14  9:04     ` Dmitry A. Kazakov
2004-01-17  0:15       ` Kenneth Almquist
2004-01-17 21:15         ` Robert A Duff
2004-01-19 10:25         ` Dmitry A. Kazakov
2004-01-13 13:13 ` Marin David Condic
2004-01-13 17:38   ` Warren W. Gay VE3WWG
2004-01-13 19:09     ` Robert A Duff
2004-01-15 17:30       ` Warren W. Gay VE3WWG
2004-01-15 18:11         ` Robert A Duff
2004-01-15 19:36           ` tmoran
2004-01-15 20:35             ` Robert A Duff
2004-01-17  5:48               ` Robert I. Eachus
2004-01-16  1:52           ` Redefining := (was: The "()" operator revisited.) Jeffrey Carter
2004-01-16 21:37             ` Randy Brukardt
2004-01-19 11:33               ` Dmitry A. Kazakov
2004-01-16  3:11           ` The "()" operator revisited Mark A. Biggar
2004-01-16 13:28             ` Hyman Rosen
2004-01-16 16:19             ` Robert A Duff
2004-01-16 18:09             ` Warren W. Gay VE3WWG
2004-01-16 13:56           ` Frank J. Lhota
2004-01-16 16:14             ` Robert A Duff
2004-01-16 21:29               ` Frank J. Lhota
  -- strict thread matches above, loose matches on Subject: below --
2004-01-13 17:46 amado.alves
2004-01-13 22:21 ` Randy Brukardt
2004-01-13 17:53 amado.alves
2004-01-14  9:09 ` Dmitry A. Kazakov
2004-01-14 12:55   ` Georg Bauhaus
2004-01-14 15:05     ` Dmitry A. Kazakov
2004-01-15  1:21       ` Georg Bauhaus
2004-01-15  8:50         ` Dmitry A. Kazakov
2004-01-15 11:09           ` Georg Bauhaus
2004-01-15 13:23             ` Dmitry A. Kazakov
2004-01-17  6:26               ` Robert I. Eachus
2004-01-14 13:04   ` Hyman Rosen
2004-01-14 15:22 amado.alves
2004-01-14 16:16 ` 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