comp.lang.ada
 help / color / mirror / Atom feed
* Rational for not making cursor tagged in Containers
@ 2007-04-19 16:05 Anh Vo
  2007-04-19 18:25 ` Robert A Duff
  2007-04-20  2:53 ` Randy Brukardt
  0 siblings, 2 replies; 66+ messages in thread
From: Anh Vo @ 2007-04-19 16:05 UTC (permalink / raw)


I enjoy using the prefixed (object) notation when and where ever I
can. However, when it comes to Containers, I can not use this notation
on cursor because it is not tagged.

It seems that it is not balanced between Container types and its
cursors. I just want to know what rationale behind it for not making
cursor a tagged type.

AV




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

* Re: Rational for not making cursor tagged in Containers
  2007-04-19 16:05 Rational for not making cursor tagged in Containers Anh Vo
@ 2007-04-19 18:25 ` Robert A Duff
  2007-04-19 19:28   ` Anh Vo
  2007-04-20  3:03   ` Randy Brukardt
  2007-04-20  2:53 ` Randy Brukardt
  1 sibling, 2 replies; 66+ messages in thread
From: Robert A Duff @ 2007-04-19 18:25 UTC (permalink / raw)


Anh Vo <anhvofrcaus@gmail.com> writes:

> I enjoy using the prefixed (object) notation when and where ever I
> can. However, when it comes to Containers, I can not use this notation
> on cursor because it is not tagged.
>
> It seems that it is not balanced between Container types and its
> cursors. I just want to know what rationale behind it for not making
> cursor a tagged type.

I suppose it's because there's no need for type extension or dispatching
calls.  So why pay the overhead?

A different question might be: Why is the prefix notation not allowed
for untagged types?  I don't know the answer to that, but it's probably
documented in the relevant AI.

I'm not a big fan of prefix notation, by the way.

- Bob



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-19 18:25 ` Robert A Duff
@ 2007-04-19 19:28   ` Anh Vo
  2007-04-19 20:45     ` Robert A Duff
  2007-04-20  3:03   ` Randy Brukardt
  1 sibling, 1 reply; 66+ messages in thread
From: Anh Vo @ 2007-04-19 19:28 UTC (permalink / raw)


On Apr 19, 11:25 am, Robert A Duff <bobd...@shell01.TheWorld.com>
wrote:
> Anh Vo <anhvofrc...@gmail.com> writes:
> > I enjoy using the prefixed (object) notation when and where ever I
> > can. However, when it comes to Containers, I can not use this notation
> > on cursor because it is not tagged.
>
> > It seems that it is not balanced between Container types and its
> > cursors. I just want to know what rationale behind it for not making
> > cursor a tagged type.
>
> I suppose it's because there's no need for type extension or dispatching
> calls.  So why pay the overhead?

Well, I have not yet come across the situation where a Container type
needs to be extended. And yet, overhead was already paid.

> A different question might be: Why is the prefix notation not allowed
> for untagged types?  I don't know the answer to that, but it's probably
> documented in the relevant AI.

Then, it is not an extended (objectable) type. I will look for it.

> I'm not a big fan of prefix notation, by the way.

It is not uncommon that different people have different thinking. For
me prefixed notation clearly has advantages. Of course, I like to use
them to the fullest :-)

AV




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

* Re: Rational for not making cursor tagged in Containers
  2007-04-19 19:28   ` Anh Vo
@ 2007-04-19 20:45     ` Robert A Duff
  2007-04-19 21:43       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Robert A Duff @ 2007-04-19 20:45 UTC (permalink / raw)


Anh Vo <anhvofrcaus@gmail.com> writes:

> On Apr 19, 11:25 am, Robert A Duff <bobd...@shell01.TheWorld.com>
> wrote:
>>
>> I suppose it's because there's no need for type extension or dispatching
>> calls.  So why pay the overhead?
>
> Well, I have not yet come across the situation where a Container type
> needs to be extended. And yet, overhead was already paid.

True.

I think the rationale is that container types typically need
finalization, so they need to be derived from Controlled, so they are
tagged.  It was not necessary to make them VISIBLY tagged, but
I think the idea was "why not?".  You're paying for the tag
anyway, whether or not it's in the visible part.

That leads to the question, why can't we have untagged types with
finalization?  The answer is that during Ada 9X, the
derive-from-controlled idea was thought to be the simplest.
And finalization almost didn't make it into Ada 95.

>> A different question might be: Why is the prefix notation not allowed
>> for untagged types?  I don't know the answer to that, but it's probably
>> documented in the relevant AI.
>
> Then, it is not an extended (objectable) type. I will look for it.

And another question: why can't untagged types be extended?
That was allowed in the original design for Ada 9X.
Tags are needed for dispatching, but they are not needed
for extension.

>> I'm not a big fan of prefix notation, by the way.
>
> It is not uncommon that different people have different thinking. For
> me prefixed notation clearly has advantages. Of course, I like to use
> them to the fullest :-)

There is an advantage: If you have type P1.T1, with operation Mumble,
and P2.T2 extends P1.T1, and X is of type T2, do I say "P1.Mumble(X, ...)",
or "P2.Mumble(X, ...)"?  It's confusing, because it depends whether Mumble
is class-wide or dispatching, which is a conceptually minor
distinction.  And it's not unusual to change from dispatching
to class-wide.  The notation "X.Mumble(...)" avoids that confusion.

Nonetheless, it just seems weird to me to pretend that Mumble
is inside X, like a component.  There must be a better way.

- Bob



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-19 20:45     ` Robert A Duff
@ 2007-04-19 21:43       ` Dmitry A. Kazakov
  2007-04-19 23:59         ` Ray Blaak
  2007-04-20  1:18         ` Anh Vo
  0 siblings, 2 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-19 21:43 UTC (permalink / raw)


On Thu, 19 Apr 2007 16:45:36 -0400, Robert A Duff wrote:

>>> I'm not a big fan of prefix notation, by the way.
>>
>> It is not uncommon that different people have different thinking. For
>> me prefixed notation clearly has advantages. Of course, I like to use
>> them to the fullest :-)
> 
> There is an advantage: If you have type P1.T1, with operation Mumble,
> and P2.T2 extends P1.T1, and X is of type T2, do I say "P1.Mumble(X, ...)",
> or "P2.Mumble(X, ...)"?  It's confusing, because it depends whether Mumble
> is class-wide or dispatching, which is a conceptually minor
> distinction.  And it's not unusual to change from dispatching
> to class-wide.  The notation "X.Mumble(...)" avoids that confusion.

(it replaces one confusion with several others)

> Nonetheless, it just seems weird to me to pretend that Mumble
> is inside X, like a component.  There must be a better way.

The answer could be: fix renaming. The class-wide P1.Mumble should be
automatically renamed to P2.Mumble and the result should not conflict with
the original if the latter is visible. The rule could be that upon
derivation all class-wides were renamed in the current scope.

----------
I think prefix notation is rubbish. There should be an abstract member
interface allowing users creation of whatever "members" they wished. So if
anybody liked prefix notation, he could say: Mumble implements ".Mumble."
Done. Why should the language do this by default?

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-19 21:43       ` Dmitry A. Kazakov
@ 2007-04-19 23:59         ` Ray Blaak
  2007-04-20  7:54           ` Dmitry A. Kazakov
  2007-04-20  1:18         ` Anh Vo
  1 sibling, 1 reply; 66+ messages in thread
From: Ray Blaak @ 2007-04-19 23:59 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> I think prefix notation is rubbish. There should be an abstract member
> interface allowing users creation of whatever "members" they wished. So if
> anybody liked prefix notation, he could say: Mumble implements ".Mumble."
> Done. Why should the language do this by default?

Because record types have prefix notation for fields, protected objects have
them for subprograms and entries, tasks have them for entries.

So the real question is, why *not* have them for tagged object methods.

The typical OO languages encourage the obj.method notation, and this is useful
when one thinks of an object as owning its behaviour, rather than the
package/namespace it was declared.

Now if you don't agree with this style of OO approach, then fortunately Ada
allows the Method(obj) notation.

It is the lack of the prefix notation that was probably the primary reason for
turning me into an ex-Ada fanatic.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-19 21:43       ` Dmitry A. Kazakov
  2007-04-19 23:59         ` Ray Blaak
@ 2007-04-20  1:18         ` Anh Vo
  2007-04-20  7:53           ` Dmitry A. Kazakov
  2007-04-20 11:59           ` Jean-Pierre Rosen
  1 sibling, 2 replies; 66+ messages in thread
From: Anh Vo @ 2007-04-20  1:18 UTC (permalink / raw)


On Apr 19, 2:43 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Thu, 19 Apr 2007 16:45:36 -0400, Robert A Duff wrote:
>
> > There is an advantage: If you have type P1.T1, with operation Mumble,
> > and P2.T2 extends P1.T1, and X is of type T2, do I say "P1.Mumble(X, ...)",
> > or "P2.Mumble(X, ...)"?  It's confusing, because it depends whether Mumble
> > is class-wide or dispatching, which is a conceptually minor
> > distinction.  And it's not unusual to change from dispatching
> > to class-wide.  The notation "X.Mumble(...)" avoids that confusion.
>
> (it replaces one confusion with several others)

I do not understand what other confusions do you refer to. Other
advantage of prefix notation is that I do not have to fully qualify
nor apply use clause.

> I think prefix notation is rubbish. There should be an abstract member
> interface allowing users creation of whatever "members" they wished. So if
> anybody liked prefix notation, he could say: Mumble implements ".Mumble."
> Done. Why should the language do this by default?

This is a separate issue. I am going with the current standard. One
more thing, I usually heard the complain from the other side that Ada
is too verbose (more typing). My reply is that now Ada is shorter the
other language by two characters as shown below where X is the object
and op is the operation.

Ada                                  Other OO language
X.op;                                 X.op();

AV




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

* Re: Rational for not making cursor tagged in Containers
  2007-04-19 16:05 Rational for not making cursor tagged in Containers Anh Vo
  2007-04-19 18:25 ` Robert A Duff
@ 2007-04-20  2:53 ` Randy Brukardt
  2007-04-20 16:08   ` Anh Vo
  1 sibling, 1 reply; 66+ messages in thread
From: Randy Brukardt @ 2007-04-20  2:53 UTC (permalink / raw)


"Anh Vo" <anhvofrcaus@gmail.com> wrote in message
news:1176998738.656903.141250@q75g2000hsh.googlegroups.com...
> I enjoy using the prefixed (object) notation when and where ever I
> can. However, when it comes to Containers, I can not use this notation
> on cursor because it is not tagged.
>
> It seems that it is not balanced between Container types and its
> cursors. I just want to know what rationale behind it for not making
> cursor a tagged type.

I think there are two reasons:

(1) The original designer of the containers library intended for cursors to
be implemented as a bare access value; adding a tag makes that messier and
doubles the size of the cursors. I personally don't find this too important.

(2) Ada does not allow an operation to be primitive for two tagged types.
(I'm sure we'll hear at length from Dmitry on this. ;-) That would mean that
operations like:
     procedure Delete (Container : in out Vector; Index : in Cursor);
would be illegal. That could be worked around by making the cursor
classwide:
     procedure Delete (Container : in out Vector; Index : in Cursor'Class);
but now you don't have much taggedness left. On most operations, you're not
even losing prefix notation (as the cursor is the second parameter).

Indeed, the real reason for your problem is that container is implicit in
Cursor operations that read from the container:
     function Element (Position : Cursor) return Element_Type;

A prefix call like
    My_Cursor.Element
doesn't make much sense, because a cursor is just an accessor, you're not
extracting the element from it! You really ought to be able to say:
   My_Container.Element (Position => My_Cursor)
which makes it clear where the element is coming from.

I admit we didn't think much about these issues. When it was suggested that
perhaps the container type should be visibly tagged, I recall someone noted
that would allow the prefix notation. And that seemed good; but I don't
think anyone noted that it doesn't work sometimes.

                                    Randy.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-19 18:25 ` Robert A Duff
  2007-04-19 19:28   ` Anh Vo
@ 2007-04-20  3:03   ` Randy Brukardt
  1 sibling, 0 replies; 66+ messages in thread
From: Randy Brukardt @ 2007-04-20  3:03 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wccodlkz0ej.fsf@shell01.TheWorld.com...
...
> A different question might be: Why is the prefix notation not allowed
> for untagged types?  I don't know the answer to that, but it's probably
> documented in the relevant AI.

It originally was allowed for access types. But it got really confusing for
access type prefixes; there might have been many legal possibilities (once
you take into account implied dereferences and 'Accesses). It might be
necessary to look at several sets of primitive operations (both for the
access type, and for a designated type), and unusual ambiguities could
result. A compiler could work it out, but whether a human programmer could
was contentious. So we dropped untagged prefixes in order that we got
prefixed notation for OOP purposes (the general one might never have been
accepted).

                                   Randy.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20  1:18         ` Anh Vo
@ 2007-04-20  7:53           ` Dmitry A. Kazakov
  2007-04-20  9:26             ` Maciej Sobczak
  2007-04-20 11:59           ` Jean-Pierre Rosen
  1 sibling, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-20  7:53 UTC (permalink / raw)


On 19 Apr 2007 18:18:04 -0700, Anh Vo wrote:

> On Apr 19, 2:43 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> On Thu, 19 Apr 2007 16:45:36 -0400, Robert A Duff wrote:
>>
>>> There is an advantage: If you have type P1.T1, with operation Mumble,
>>> and P2.T2 extends P1.T1, and X is of type T2, do I say "P1.Mumble(X, ...)",
>>> or "P2.Mumble(X, ...)"?  It's confusing, because it depends whether Mumble
>>> is class-wide or dispatching, which is a conceptually minor
>>> distinction.  And it's not unusual to change from dispatching
>>> to class-wide.  The notation "X.Mumble(...)" avoids that confusion.
>>
>> (it replaces one confusion with several others)
> 
> I do not understand what other confusions do you refer to.

A confusion is in assumption that some arguments of an operation are more
arguments than others. Another is that primitive operations belong to the
object (instance). The third confusion raises from incompatibility of the
prefix notation with multi-methods and multiple dispatching operations.

> Other
> advantage of prefix notation is that I do not have to fully qualify
> nor apply use clause.

When there is something wrong with use-clauses *that* should be fixed.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-19 23:59         ` Ray Blaak
@ 2007-04-20  7:54           ` Dmitry A. Kazakov
  2007-04-20 10:56             ` Georg Bauhaus
  2007-04-20 17:05             ` Rational for not making cursor tagged in Containers Ray Blaak
  0 siblings, 2 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-20  7:54 UTC (permalink / raw)


On Thu, 19 Apr 2007 23:59:13 GMT, Ray Blaak wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> I think prefix notation is rubbish. There should be an abstract member
>> interface allowing users creation of whatever "members" they wished. So if
>> anybody liked prefix notation, he could say: Mumble implements ".Mumble."
>> Done. Why should the language do this by default?
> 
> Because record types have prefix notation for fields, protected objects have
> them for subprograms and entries, tasks have them for entries.

Record type is just an implementation of some ADT. There is no any semantic
difference between records, arrays, integers etc in that respect. That a
given private implementation occasionally has any fields is an
implementation detail.

In a better language any type could be able implement record interface:

   type Foo is interface record  -- This not an implementation!
      Mumble : Integer;
   end record;
private
   type Foo is new Float; -- Implements the record interface
   function "Mumble" (X :  Foo) return Integer; -- Getter
   procedure "Mumble" (X : in out Foo; Value : Integer); -- Setter

> So the real question is, why *not* have them for tagged object methods.
>
> The typical OO languages encourage the obj.method notation, and this is useful
> when one thinks of an object as owning its behaviour, rather than the
> package/namespace it was declared.

X := Y; -- Who owns assignment? 1 or X?

And, what makes you think that OO defines methods (primitive operations) as
the behavior? (We can continue this in comp.object if you want.)

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20  7:53           ` Dmitry A. Kazakov
@ 2007-04-20  9:26             ` Maciej Sobczak
  2007-04-20 10:15               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Maciej Sobczak @ 2007-04-20  9:26 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> A confusion is in assumption that some arguments of an operation are more
> arguments than others.

There is some rationale for this, however.
With the traditionally abstract OO, operations are executed as a result 
of messages that are sent to objects. Now that indeed gives some objects 
more focus than others.

This:

a.op(b);

means (supposedly) that "op" message is sent to object "a" and the 
payload of the message is "b".

I agree that it introduces some asymetry that is not necessarily needed.
I mean - the above abstraction is not necessarily the best one, but 
serves me well as an explanation of the a.op(b) issue.

> Another is that primitive operations belong to the
> object (instance).

No, but it makes sense to think that they belong to the type of some object.

> The third confusion raises from incompatibility of the
> prefix notation with multi-methods and multiple dispatching operations.

True. But then, the above messaging abstractions needs to be extended to 
cover "multicasts". :-)

>> Other
>> advantage of prefix notation is that I do not have to fully qualify
>> nor apply use clause.
> 
> When there is something wrong with use-clauses *that* should be fixed.

I agree that the lack of ADL (Argument-Dependent Lookup) in Ada sucks.

-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20  9:26             ` Maciej Sobczak
@ 2007-04-20 10:15               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-20 10:15 UTC (permalink / raw)


On Fri, 20 Apr 2007 11:26:08 +0200, Maciej Sobczak wrote:

> Dmitry A. Kazakov wrote:
> 
>> A confusion is in assumption that some arguments of an operation are more
>> arguments than others.
> 
> There is some rationale for this, however.
> With the traditionally abstract OO, operations are executed as a result 
> of messages that are sent to objects. Now that indeed gives some objects 
> more focus than others.
> 
> This:
> 
> a.op(b);
> 
> means (supposedly) that "op" message is sent to object "a" and the 
> payload of the message is "b".
> 
> I agree that it introduces some asymetry that is not necessarily needed.
> I mean - the above abstraction is not necessarily the best one, but 
> serves me well as an explanation of the a.op(b) issue.

Ah, yes, messaging is an interesting issue.

>> Another is that primitive operations belong to the
>> object (instance).
> 
> No, but it makes sense to think that they belong to the type of some object.

They do, if all arguments had the same type. But if they don't?

>> The third confusion raises from incompatibility of the
>> prefix notation with multi-methods and multiple dispatching operations.
> 
> True. But then, the above messaging abstractions needs to be extended to 
> cover "multicasts". :-)

That is one problem. Another is that you still have dedicated arguments,
i.e. ones marshaled (parameters) and ones referenced (recipients). But it
is not in Ada way to distinguish by-copy and by-reference. Why should
anybody care, why should it be syntactically highlighted? Another problem
is the sender. The sugar a.op(b) tells nothing about who issued the
message. While the paradigm tells about messages sent *between* objects.
This adds additional asymmetry, c, the sender is invisible and actually is
a context rather than object. I.e. there are three animals:

1. the recipient (a fully decorated object, blue blood)

2. the parameter[s] (value, hard-wired thing nobody knows what,
"non-tagged", as Ada calls it (:-))

3. the sender's context, which is even not a value.

Looks like a mess, even without multicasting, or messages with acknowledge,
or remote calls on local objects...

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 10:56             ` Georg Bauhaus
@ 2007-04-20 10:39               ` Dmitry A. Kazakov
  2007-04-20 14:42                 ` Georg Bauhaus
  0 siblings, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-20 10:39 UTC (permalink / raw)


On Fri, 20 Apr 2007 12:56:23 +0200, Georg Bauhaus wrote:

> On Fri, 2007-04-20 at 09:54 +0200, Dmitry A. Kazakov wrote:
> 
>> In a better language any type could be able implement record interface:
>> 
>>    type Foo is interface record  -- This not an implementation!
>>       Mumble : Integer;
>>    end record;
>> private
>>    type Foo is new Float; -- Implements the record interface
>>    function "Mumble" (X :  Foo) return Integer; -- Getter
>>    procedure "Mumble" (X : in out Foo; Value : Integer); -- Setter
> 
> C# and Eiffel do it this way; I'm almost sure there is a bunch of
> Lisp macros achieving the same. But I think approaching simple records
> like this will be a huge mistake in a language like Ada, for the
> following reason: When a user of your type see the above definition
> 
>    type Foo is interface record ...
> 
> it means that he or she will *have* to look at the implementation
> (or hope for extensive documentation): There is no
> way of knowing whether reading or writing a record component will
> just move some bits, or try to compute the first prime number of
> the 1969 lottery on the way.

And you claim to know it. Always? With all possible pragmas applied,
including Pack, as well as representation clauses like for X'Address use
...? As for me, I don't know it in 90% cases, and in 99% of these, I just
don't care. Ada is known a safe language (tm), which assumes not only safe
primitives but also a safe composition of.

BTW, Ada has private types from the day one.

> And, considering Controlled, forcing *all* types to be derived
> from this base suffers from the same effects for the same reason.

Because multiple-inheritance is *the* answer. You need not to force anybody
to anything if an interface (and an implementation of) can be added later.

There indeed exist very hard interfaces to add later, like the task
interface or the protected interface. But more things you have hard-wired
in the language, more complex it becomes for everybody, you, me, the
compiler vendor and the Pentium.

> Not every programming team consists of real or even wannabe
> language designers. But who else has even got a chance of knowing
> what they are doing to a larger program when implementing the
> concept of record?

Why they are allowed to implement a concept of task, but not one of getter
and setter? Where do you draw the line?

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20  7:54           ` Dmitry A. Kazakov
@ 2007-04-20 10:56             ` Georg Bauhaus
  2007-04-20 10:39               ` Dmitry A. Kazakov
  2007-04-20 17:05             ` Rational for not making cursor tagged in Containers Ray Blaak
  1 sibling, 1 reply; 66+ messages in thread
From: Georg Bauhaus @ 2007-04-20 10:56 UTC (permalink / raw)


On Fri, 2007-04-20 at 09:54 +0200, Dmitry A. Kazakov wrote:

> In a better language any type could be able implement record interface:
> 
>    type Foo is interface record  -- This not an implementation!
>       Mumble : Integer;
>    end record;
> private
>    type Foo is new Float; -- Implements the record interface
>    function "Mumble" (X :  Foo) return Integer; -- Getter
>    procedure "Mumble" (X : in out Foo; Value : Integer); -- Setter

C# and Eiffel do it this way; I'm almost sure there is a bunch of
Lisp macros achieving the same. But I think approaching simple records
like this will be a huge mistake in a language like Ada, for the
following reason: When a user of your type see the above definition

   type Foo is interface record ...

it means that he or she will *have* to look at the implementation
(or hope for extensive documentation): There is no
way of knowing whether reading or writing a record component will
just move some bits, or try to compute the first prime number of
the 1969 lottery on the way.

Having programmers implement record abstractions looses all
predictability that the LRM can otherwise provide for simple
records. We need some simple, fixed, stupid things outside
the control of programmers. (More politely, leave some
things to a compiler.)
 And, considering Controlled, forcing *all* types to be derived
from this base suffers from the same effects for the same reason.

Not every programming team consists of real or even wannabe
language designers. But who else has even got a chance of knowing
what they are doing to a larger program when implementing the
concept of record?





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20  1:18         ` Anh Vo
  2007-04-20  7:53           ` Dmitry A. Kazakov
@ 2007-04-20 11:59           ` Jean-Pierre Rosen
  2007-04-20 13:23             ` Anh Vo
  1 sibling, 1 reply; 66+ messages in thread
From: Jean-Pierre Rosen @ 2007-04-20 11:59 UTC (permalink / raw)


Anh Vo a �crit :
> I do not understand what other confusions do you refer to. Other
> advantage of prefix notation is that I do not have to fully qualify
> nor apply use clause.
> 
And one advantage of use clause is that you don't have to use prefix 
notation ;-)

-- 
---------------------------------------------------------
            J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 11:59           ` Jean-Pierre Rosen
@ 2007-04-20 13:23             ` Anh Vo
  2007-04-20 16:02               ` Jean-Pierre Rosen
  0 siblings, 1 reply; 66+ messages in thread
From: Anh Vo @ 2007-04-20 13:23 UTC (permalink / raw)


On Apr 20, 4:59 am, Jean-Pierre Rosen <r...@adalog.fr> wrote:
> Anh Vo a écrit :> I do not understand what other confusions do you refer to. Other
> > advantage of prefix notation is that I do not have to fully qualify
> > nor apply use clause.
>
> And one advantage of use clause is that you don't have to use prefix
> notation ;-)

It is true. However, using use clause does not fit advantage category.
In addition, the side effect of using use clause, for most cases,
leans toward disadvantage side :-(

AV




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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 10:39               ` Dmitry A. Kazakov
@ 2007-04-20 14:42                 ` Georg Bauhaus
  2007-04-20 14:45                   ` Georg Bauhaus
  2007-04-20 15:13                   ` Dmitry A. Kazakov
  0 siblings, 2 replies; 66+ messages in thread
From: Georg Bauhaus @ 2007-04-20 14:42 UTC (permalink / raw)


On Fri, 2007-04-20 at 12:39 +0200, Dmitry A. Kazakov wrote:
> On Fri, 20 Apr 2007 12:56:23 +0200, Georg Bauhaus wrote:

> >    type Foo is interface record ...
> >  ... There is no
> > way of knowing whether reading or writing a record component will
> > just move some bits, or try to compute the first prime number of
> > the 1969 lottery on the way.
> 
> And you claim to know it. Always? With all possible pragmas applied,
> including Pack, as well as representation clauses like for X'Address use
> ...?

The practical difference between a simple record and a programmer-
defined record interface implementation is a set of fixed rules in
the first case and full (sub)programs in the second case.

>  As for me, I don't know it in 90% cases, and in 99% of these, I just
> don't care.

Right, I assume you don't care to known what an assignment to
a record component does because you either rely on the
thing being a "sufficiently normal" data component or you can
trust the authors of the program and assume they haven't
introduced an overly ambitious algorithm for Adjust that
would let your application hang for a while.

> BTW, Ada has private types from the day one.

If the type in question is private, there is nothing
to argue about. But your record type construction interface
wasn't private; and it didn't announce that Mumble isn't
just a record component. To emphasize: I don't want to loose
comparatively simple building blocks (records) just because
some smart programmers can build similar things (implementing
record interfaces) with more effects. I'm not forced to provide
get {} and set {} in C#, and neither assigners in Eiffel.


> > And, considering Controlled, forcing *all* types to be derived
> > from this base suffers from the same effects for the same reason.
> 
> Because multiple-inheritance is *the* answer. You need not to force anybody
> to anything if an interface (and an implementation of) can be added later.

This is where it becomes dangerous, I think. Suggesting that programmers
can implement "linguistic interfaces" forces programmers to be language
designers, profiting from decades of language research, compilation
technology, etc. etc..


> But more things you have hard-wired
> in the language, more complex it becomes for everybody, you, me, the
> compiler vendor and the Pentium.

If the hard-wired features of a language don't suit your problem, or
your solution, it might become a complex issue to work around
the language. Using a language construction language (sic) that suits
your problem solution will be a more pleasant experience. But for whom?
A reader will have to acquire complex language construction language
rules; just as look-at-my-neat-domain-language-macros
are both clever and not recommended in the general case (by Graham).



> > Not every programming team consists of real or even wannabe
> > language designers. But who else has even got a chance of knowing
> > what they are doing to a larger program when implementing the
> > concept of record?
> 
> Why they are allowed to implement a concept of task,

Uh, what do you mean? Ordering entry calls? Specifying rules
of conditional acceptance? In the more common case, I find
that much better than using a language that "gives you the
freedom to roll your own" tasking.

>  Where do you draw the line?

For a general purpose language, I draw the line where the
programmers would otherwise be forced to fiddle with
the tiny bits usually done by compilers. The operations
of private types are not tiny bits, but forcing plain record
component assignments to be full subprograms should not be
the default in Ada.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 14:42                 ` Georg Bauhaus
@ 2007-04-20 14:45                   ` Georg Bauhaus
  2007-04-20 15:13                   ` Dmitry A. Kazakov
  1 sibling, 0 replies; 66+ messages in thread
From: Georg Bauhaus @ 2007-04-20 14:45 UTC (permalink / raw)


On Fri, 2007-04-20 at 16:42 +0200, Georg Bauhaus wrote:

>  <del>and it didn't announce that Mumble isn't
> just a record component.</del>





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 14:42                 ` Georg Bauhaus
  2007-04-20 14:45                   ` Georg Bauhaus
@ 2007-04-20 15:13                   ` Dmitry A. Kazakov
  2007-04-20 19:37                     ` Georg Bauhaus
  2007-04-20 20:11                     ` Randy Brukardt
  1 sibling, 2 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-20 15:13 UTC (permalink / raw)


On Fri, 20 Apr 2007 16:42:27 +0200, Georg Bauhaus wrote:

> On Fri, 2007-04-20 at 12:39 +0200, Dmitry A. Kazakov wrote:

>> BTW, Ada has private types from the day one.
> 
> If the type in question is private, there is nothing
> to argue about.

It is private.

> To emphasize: I don't want to loose
> comparatively simple building blocks (records) just because
> some smart programmers can build similar things (implementing
> record interfaces) with more effects. I'm not forced to provide
> get {} and set {} in C#, and neither assigners in Eiffel.

This is confused. Are you talking about composition of types or about usage
of?

If it is the latter, then you already lost, because prefix notation is used
in Ada for gazillion unrelated things. You cannot tell what X.A means
without the context. And this is right.
 
If you are talking about the former, then what is lost? You still can use
plain records as an abbreviation to: this implements a record interface and
surprisingly is also built-it record.

> This is where it becomes dangerous, I think. Suggesting that programmers
> can implement "linguistic interfaces" forces programmers to be language
> designers, profiting from decades of language research, compilation
> technology, etc. etc..

Honestly, I don't see what is so especially dangerous in X.A as compared to
A(X).

>>> Not every programming team consists of real or even wannabe
>>> language designers. But who else has even got a chance of knowing
>>> what they are doing to a larger program when implementing the
>>> concept of record?
>> 
>> Why they are allowed to implement a concept of task,
> 
> Uh, what do you mean?

I mean they are allowed to write

   task type X is

but not

   record type X is

(as opposed to type Y is record [X])

IMO, task is far more conceptually complex than a container of fixed number
of elements indexed by statically known strings.

>>  Where do you draw the line?
> 
> For a general purpose language, I draw the line where the
> programmers would otherwise be forced to fiddle with
> the tiny bits usually done by compilers. The operations
> of private types are not tiny bits, but forcing plain record
> component assignments to be full subprograms should not be
> the default in Ada.

Uhm, default of what? I wish to have record interfaces, nothing more. I
don't see nothing special in record containers. I cannot understand why a
record view should enforce anything on the implementation of, beyond that
view. Also I fail to understand why polymorphic objects has to be records
and not arrays or access types. Why array or number cannot have
discriminants, but records can? Why array element cannot be extracted using
X."Foo", and why record item cannot be using X("Foo"). etc.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 13:23             ` Anh Vo
@ 2007-04-20 16:02               ` Jean-Pierre Rosen
  2007-04-21  2:53                 ` Anh Vo
  0 siblings, 1 reply; 66+ messages in thread
From: Jean-Pierre Rosen @ 2007-04-20 16:02 UTC (permalink / raw)


Anh Vo a �crit :
> On Apr 20, 4:59 am, Jean-Pierre Rosen <r...@adalog.fr> wrote:
>> Anh Vo a �crit :> I do not understand what other confusions do you refer to. Other
>>> advantage of prefix notation is that I do not have to fully qualify
>>> nor apply use clause.
>> And one advantage of use clause is that you don't have to use prefix
>> notation ;-)
> 
> It is true. However, using use clause does not fit advantage category.
> In addition, the side effect of using use clause, for most cases,
> leans toward disadvantage side :-(
> 
A common opinion, but far from being universal (although voiced louder 
than the opposite).

For those of us who do not write Level-A software, use clauses increase 
readability, while keeping precise control over name space by opening 
visibility at the innermost level where it is needed.

Of course, this assume that you use use clauses properly, and not after 
each with clause!

-- 
---------------------------------------------------------
            J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20  2:53 ` Randy Brukardt
@ 2007-04-20 16:08   ` Anh Vo
  0 siblings, 0 replies; 66+ messages in thread
From: Anh Vo @ 2007-04-20 16:08 UTC (permalink / raw)


On Apr 19, 7:53 pm, "Randy Brukardt" <r...@rrsoftware.com> wrote:
> "Anh Vo" <anhvofrc...@gmail.com> wrote in message
>
> > It seems that it is not balanced between Container types and its
> > cursors. I just want to know what rationale behind it for not making
> > cursor a tagged type.
>
> I think there are two reasons:
>
> (1) The original designer of the containers library intended for cursors to
> be implemented as a bare access value; adding a tag makes that messier and
> doubles the size of the cursors. I personally don't find this too important.
>
> (2) Ada does not allow an operation to be primitive for two tagged types.
> (I'm sure we'll hear at length from Dmitry on this. ;-) That would mean that
> operations like:
>      procedure Delete (Container : in out Vector; Index : in Cursor);
> would be illegal. That could be worked around by making the cursor
> classwide:

Thanks for your explanation. Reason in (2) is more legitimate.

>      procedure Delete (Container : in out Vector; Index : in Cursor'Class);
> but now you don't have much taggedness left. On most operations, you're not
> even losing prefix notation (as the cursor is the second parameter).

agreed.

> Indeed, the real reason for your problem is that container is implicit in
> Cursor operations that read from the container:
>      function Element (Position : Cursor) return Element_Type;
>
> A prefix call like
>     My_Cursor.Element
> doesn't make much sense, because a cursor is just an accessor, you're not
> extracting the element from it! You really ought to be able to say:
>    My_Container.Element (Position => My_Cursor)
> which makes it clear where the element is coming from.

The latter is already given. I am not quite agreed with the former
because I do not see any thing wrong to extract an element pointed by
an accessor if and only if Cursor is tagged.

> I admit we didn't think much about these issues. When it was suggested that
> perhaps the container type should be visibly tagged, I recall someone noted
> that would allow the prefix notation. And that seemed good; but I don't
> think anyone noted that it doesn't work sometimes.

It is a good lesson learned.

AV





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20  7:54           ` Dmitry A. Kazakov
  2007-04-20 10:56             ` Georg Bauhaus
@ 2007-04-20 17:05             ` Ray Blaak
  2007-04-20 18:46               ` Dmitry A. Kazakov
  1 sibling, 1 reply; 66+ messages in thread
From: Ray Blaak @ 2007-04-20 17:05 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> In a better language any type could be able implement record interface:
> 
>    type Foo is interface record  -- This not an implementation!
>       Mumble : Integer;
>    end record;
> private
>    type Foo is new Float; -- Implements the record interface
>    function "Mumble" (X :  Foo) return Integer; -- Getter
>    procedure "Mumble" (X : in out Foo; Value : Integer); -- Setter

As long as I can use prefix notation then I would be ok with this, e.g given
f:Foo, I can say f.Mumble := 2

Otherwise, ugh.

> 
> X := Y; -- Who owns assignment? 1 or X?

X, of course.

> 
> And, what makes you think that OO defines methods (primitive operations) as
> the behavior? (We can continue this in comp.object if you want.)

I don't know how else to define behaviour except via methods :-).

As to differences in beliefs regarding OO philsophies, I am not going to go
there, except to observer that Ada allows multiple approaches to work.

My point is only that my preferred conceptualizations of OO abstractions leads
me to prefer an obj.member notation, and I choose languages that allow that.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 17:05             ` Rational for not making cursor tagged in Containers Ray Blaak
@ 2007-04-20 18:46               ` Dmitry A. Kazakov
  2007-04-20 18:52                 ` Ray Blaak
  0 siblings, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-20 18:46 UTC (permalink / raw)


On Fri, 20 Apr 2007 17:05:28 GMT, Ray Blaak wrote:

>> X := Y; -- Who owns assignment? 1 or X?
> 
> X, of course.

So, it should dispatch on X, right? Welcome back to C++!

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 18:46               ` Dmitry A. Kazakov
@ 2007-04-20 18:52                 ` Ray Blaak
  2007-04-20 19:54                   ` Robert A Duff
  0 siblings, 1 reply; 66+ messages in thread
From: Ray Blaak @ 2007-04-20 18:52 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> On Fri, 20 Apr 2007 17:05:28 GMT, Ray Blaak wrote:
> 
> >> X := Y; -- Who owns assignment? 1 or X?
> > 
> > X, of course.
> 
> So, it should dispatch on X, right? Welcome back to C++!

No sweat. That is not the most serious of C++'s pitfalls.

In practice though, I use C#/Java for which the "language" owns assignment,
and no one else. Of course simple assignment does not copy fields, so explicit
clone/copy methods need to be used instead, which more clearly indicates
ownership/dispatching rules, etc.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 19:37                     ` Georg Bauhaus
@ 2007-04-20 19:32                       ` Dmitry A. Kazakov
  2007-04-20 20:59                         ` Robert A Duff
  2007-04-20 19:55                       ` Randy Brukardt
  2007-04-20 20:44                       ` Robert A Duff
  2 siblings, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-20 19:32 UTC (permalink / raw)


On Fri, 20 Apr 2007 21:37:09 +0200, Georg Bauhaus wrote:

> On Fri, 2007-04-20 at 17:13 +0200, Dmitry A. Kazakov wrote:
>> You still can use
>> plain records as an abbreviation to: this implements a record interface and
>> surprisingly is also built-it record.
> 
> Except for the surprise that's fine, then. (I'm curious
> what your ideas are regarding rules for accessing sister record
> components in .Mumble procedures, elaboration order, etc.. I'm
> assuming that the thing is more than a syntactical device?)

Why should it be anything more? It is no different from any other private
type. It is the private implementation which determines presentation,
construction and finalization.

>>> This is where it becomes dangerous, I think. Suggesting that programmers
>>> can implement "linguistic interfaces" forces programmers to be language
>>> designers, profiting from decades of language research, compilation
>>> technology, etc. etc..
>> 
>> Honestly, I don't see what is so especially dangerous in X.A as compared to
>> A(X).
> 
> I had understood that plain records were to be abandoned in favor
> of a set of record interface rules not only permitting programmers to
> implement record interfaces, but instead forcing them to do
> so because record mechanisms would no longer be part of the language.

Not at all. An ability to write

   type N is range 1..100;

by no means precludes Standard.Integer.

However I can imagine guidelines and code quality requirements which would
limit public use of record types in favor of interfaces. For the same
reasons why one would argue against use of Standard.Integer.

> That is,
> 
>   X.A := whatever(expr);
> 
> must in effect become
> 
>   whatever(X, expr);

It is how it works right now. I bet any compiler generates some inlined
stuff to access record members.
 
> which does whatever it does. (Would we have
>   whatever(X, expr(T'access))
> in default initializers for limited types?)

No. Why should it? Thee is no connection between "." operation and
initialization.

But, why do you see it as a problem? Limited record [interface] is not one
of its members. You can have limited records on non-limited components.

>>>>> Not every programming team consists of real or even wannabe
>>>>> language designers. But who else has even got a chance of knowing
>>>>> what they are doing to a larger program when implementing the
>>>>> concept of record?
>>>> 
>>>> Why they are allowed to implement a concept of task,
>>> 
>>> Uh, what do you mean?
>> 
>> I mean they are allowed to write
>> 
>>    task type X is
>> 
>> but not
>> 
>>    record type X is
>> 
>> (as opposed to type Y is record [X])
>> 
>> IMO, task is far more conceptually complex than a container of fixed number
>> of elements indexed by statically known strings.
> 
> By analogy, and consistent with the desired record interfaces,
> I will be asking for task type interfaces (no, not really).

They already exist in Ada 2005.

> This is a good illustration of what I meant to say. You can choose
> between two points of view:
> 1 this gives programmers the freedom to implement their ideas
>   of a concurrent execution in a guided fashion.

No it does not, because there is no language primitive other than built-in
task to implement a task interface. For this reason it is safe. However, if
Ada would in some future provide interfacing with other concurrent
languages, one could have alternatives to built-in tasks.

>>  I cannot understand why a
>> record view should enforce anything on the implementation of, beyond that
>> view.
> 
> Maybe for ease of recognition and simplicity of prediction in typical
> systems programming?  When I see X.A := 16#FE#; and notice that X
> is of a simple record type, I expect only a small number of mishaps.

You can't. X.A is mapped to a hardware port. The bit 8 set in that port
initiates an emergency shut-down sequence...

>>  Also I fail to understand why polymorphic objects has to be records
>> and not arrays or access types. Why array or number cannot have
>> discriminants, but records can?
> 
> "Uniformity.  Discriminants make sense for any composite type.

Discriminants make sense for ANY type, be it record or Boolean.

> In Ada
> 9X, we allow them for any composite type except array types.  The
> array-type restriction is for ease of implementation -- it does not
> simplify the language nor make it easier to use.

This is disputable. There exists numerous examples when disciminants for
arrays were quite useful. The classical example is arrays of arrays:

type X is array (... range <>) of ..;
type Y is array (... range <>) of Y (??????); -- Go figure out!

It wouldn't be a problem if there were array interfaces, but they don't
exist either.

> Adding another
> restriction for task types would decrease uniformity further.
> Discriminants are allowed for protected types; disallowing them for
> tasks would make tasks a second-class citizen."
> -- http://archive.adaic.com/standards/95lsn/LSN1044.TaskDisc.txt
> 
> 
> You do not want subprogram interfaces, I presume? :-)

We already have then, they are called abstract subprograms.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 15:13                   ` Dmitry A. Kazakov
@ 2007-04-20 19:37                     ` Georg Bauhaus
  2007-04-20 19:32                       ` Dmitry A. Kazakov
                                         ` (2 more replies)
  2007-04-20 20:11                     ` Randy Brukardt
  1 sibling, 3 replies; 66+ messages in thread
From: Georg Bauhaus @ 2007-04-20 19:37 UTC (permalink / raw)


On Fri, 2007-04-20 at 17:13 +0200, Dmitry A. Kazakov wrote:
>  You still can use
> plain records as an abbreviation to: this implements a record interface and
> surprisingly is also built-it record.

Except for the surprise that's fine, then. (I'm curious
what your ideas are regarding rules for accessing sister record
components in .Mumble procedures, elaboration order, etc.. I'm
assuming that the thing is more than a syntactical device?)


> > This is where it becomes dangerous, I think. Suggesting that programmers
> > can implement "linguistic interfaces" forces programmers to be language
> > designers, profiting from decades of language research, compilation
> > technology, etc. etc..
> 
> Honestly, I don't see what is so especially dangerous in X.A as compared to
> A(X).

I had understood that plain records were to be abandoned in favor
of a set of record interface rules not only permitting programmers to
implement record interfaces, but instead forcing them to do
so because record mechanisms would no longer be part of the language.
That is,

  X.A := whatever(expr);

must in effect become

  whatever(X, expr);

which does whatever it does. (Would we have
  whatever(X, expr(T'access))
in default initializers for limited types?)




> >>> Not every programming team consists of real or even wannabe
> >>> language designers. But who else has even got a chance of knowing
> >>> what they are doing to a larger program when implementing the
> >>> concept of record?
> >> 
> >> Why they are allowed to implement a concept of task,
> > 
> > Uh, what do you mean?
> 
> I mean they are allowed to write
> 
>    task type X is
> 
> but not
> 
>    record type X is
> 
> (as opposed to type Y is record [X])
> 
> IMO, task is far more conceptually complex than a container of fixed number
> of elements indexed by statically known strings.

By analogy, and consistent with the desired record interfaces,
I will be asking for task type interfaces (no, not really).
This is a good illustration of what I meant to say. You can choose
between two points of view:
1 this gives programmers the freedom to implement their ideas
  of a concurrent execution in a guided fashion.
2 this places the burden of implementing a tasking RTS on the
  shoulders of the programmers.


>  I cannot understand why a
> record view should enforce anything on the implementation of, beyond that
> view.

Maybe for ease of recognition and simplicity of prediction in typical
systems programming?  When I see X.A := 16#FE#; and notice that X
is of a simple record type, I expect only a small number of mishaps.


>  Also I fail to understand why polymorphic objects has to be records
> and not arrays or access types. Why array or number cannot have
> discriminants, but records can?

"Uniformity.  Discriminants make sense for any composite type.  In Ada
9X, we allow them for any composite type except array types.  The
array-type restriction is for ease of implementation -- it does not
simplify the language nor make it easier to use.  Adding another
restriction for task types would decrease uniformity further.
Discriminants are allowed for protected types; disallowing them for
tasks would make tasks a second-class citizen."
-- http://archive.adaic.com/standards/95lsn/LSN1044.TaskDisc.txt


You do not want subprogram interfaces, I presume? :-)





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 18:52                 ` Ray Blaak
@ 2007-04-20 19:54                   ` Robert A Duff
  0 siblings, 0 replies; 66+ messages in thread
From: Robert A Duff @ 2007-04-20 19:54 UTC (permalink / raw)


Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> On Fri, 20 Apr 2007 17:05:28 GMT, Ray Blaak wrote:
>> 
>> >> X := Y; -- Who owns assignment? 1 or X?

Was this supposed to say "Y or X"?  Or is 1 presumed to be the value of Y?
I think I'm missing Dmitry's point here, unless it was to say that
for symmetric operations, it's hard to say which type it "belongs" to.

>> > X, of course.
>> 
>> So, it should dispatch on X, right? Welcome back to C++!
>
> No sweat. That is not the most serious of C++'s pitfalls.
>
> In practice though, I use C#/Java for which the "language" owns assignment,
> and no one else. Of course simple assignment does not copy fields, so explicit
> clone/copy methods need to be used instead, which more clearly indicates
> ownership/dispatching rules, etc.

Yeah.  In this area, Java is sort of like the situation in Ada if all
composite types were required to be limited.  You can use ":=" on access
types and integer types...

- Bob



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 19:37                     ` Georg Bauhaus
  2007-04-20 19:32                       ` Dmitry A. Kazakov
@ 2007-04-20 19:55                       ` Randy Brukardt
  2007-04-22  9:54                         ` Georg Bauhaus
  2007-04-20 20:44                       ` Robert A Duff
  2 siblings, 1 reply; 66+ messages in thread
From: Randy Brukardt @ 2007-04-20 19:55 UTC (permalink / raw)


"Georg Bauhaus" <bauhaus@futureapps.de> wrote in message
news:1177097829.26685.36.camel@localhost.localdomain...
...
> By analogy, and consistent with the desired record interfaces,
> I will be asking for task type interfaces (no, not really).

Ada already has task interfaces, so you don't need to ask. ;-)

Which is why Dmitry's point is reasonable. There are things you can't do (or
can't do safely) with private types, and why not? Shouldn't it be possible
to create a complete abstraction that works like the built-in ones?

After all, it's not about the syntax:

   X := Y;

looks simple, but I've had to debug as much as 1K of machine code that
actually implements it. There can be a lot of complexity hidden behind the
two characters ":=". There is no reason to think that it would be a problem
if '.' or '(' or '"' had similar complexity. (Indeed, there are cases where
they do, you just can't write such cases yourself.)

                      Randy.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 15:13                   ` Dmitry A. Kazakov
  2007-04-20 19:37                     ` Georg Bauhaus
@ 2007-04-20 20:11                     ` Randy Brukardt
  2007-04-20 21:28                       ` Dmitry A. Kazakov
  2007-04-21  4:48                       ` unifying arrays and records (was Re: Rational for not making cursor tagged in Containers) Ray Blaak
  1 sibling, 2 replies; 66+ messages in thread
From: Randy Brukardt @ 2007-04-20 20:11 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:1q1kx2jlcvnuj.ck0711mj4few$.dlg@40tude.net...
...
> Also I fail to understand why polymorphic objects has to be records
> and not arrays or access types. Why array or number cannot have
> discriminants, but records can?

This ones easy. There is a fundamental difference between elementary types
(which can represent only one value) and composite types (which can contain
multiple values). Adding discriminants to an elementary type would turn it
into a composite type -- and that way lies madness.

As far as why a polymorphic object has to be a record, that's simply because
it is the most general composite type. It is a heterogeneous container.
Indeed, I don't think I've ever implemented an abstraction as anything else
(at least not for long); there is always a need for additional items beyond
the main data.

The better question is why there are arrays at all. A homogeneous container
is by definition more limited than a heterogeneous one. So, the ideal
language would find a way to completely unify arrays and records. Perhaps
the array syntax would have to remain, but it would just be a language
defined synonym for a record access.

I suppose you could try to do something similar for elementary types (you
can use special syntax if there is only one component in the container), but
that would necessarily make programs fragile (adding a component would
necessarily disallow that syntax, requiring massive changes).

So, I guess the ideal language would be one in which everything was a
controlled record type. (For Janus/Ada, that's already true in many cases: a
protected type is just a special controlled record type; task objects are
essentially controlled, unconstrained arrays are really records that contain
bounds and a data pointer, etc.) But such a language would be pretty
space-inefficient (you could optimize individual calls to avoid dispatching,
but there is no way to eliminate the space overhead, because you can never
tell what might be done in some separately compiled unit.)

                                           Randy.







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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 19:37                     ` Georg Bauhaus
  2007-04-20 19:32                       ` Dmitry A. Kazakov
  2007-04-20 19:55                       ` Randy Brukardt
@ 2007-04-20 20:44                       ` Robert A Duff
  2007-04-21  5:38                         ` Randy Brukardt
  2 siblings, 1 reply; 66+ messages in thread
From: Robert A Duff @ 2007-04-20 20:44 UTC (permalink / raw)


Georg Bauhaus <bauhaus@futureapps.de> writes:

> On Fri, 2007-04-20 at 17:13 +0200, Dmitry A. Kazakov wrote:
>>  Also I fail to understand why polymorphic objects has to be records
>> and not arrays or access types. Why array or number cannot have
>> discriminants, but records can?
>
> "Uniformity.  Discriminants make sense for any composite type.  In Ada
> 9X, we allow them for any composite type except array types.  The
> array-type restriction is for ease of implementation -- it does not
> simplify the language nor make it easier to use.

Hmm... That sounds like something I would write.

>...Adding another
> restriction for task types would decrease uniformity further.
> Discriminants are allowed for protected types; disallowing them for
> tasks would make tasks a second-class citizen."
> -- http://archive.adaic.com/standards/95lsn/LSN1044.TaskDisc.txt

.... OK, I looked it up, and indeed someone named Bob Duff wrote it.
That's me!  ;-)  Thanks for the link.

In this Language Study Note (LSN), I was arguing that task types should
be allowed to have discriminants.  (And indeed they can in Ada 95 and in
Ada.)

I also thought (and continue to think) that array types should be
allowed to have discriminants.  The quote above was a jab at people
who thought otherwise.  I lost that argument.

- Bob



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 19:32                       ` Dmitry A. Kazakov
@ 2007-04-20 20:59                         ` Robert A Duff
  2007-04-20 22:14                           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Robert A Duff @ 2007-04-20 20:59 UTC (permalink / raw)


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

> On Fri, 20 Apr 2007 21:37:09 +0200, Georg Bauhaus wrote:
>> "Uniformity.  Discriminants make sense for any composite type.

Please note that I wrote the above words.  Some years ago.

> Discriminants make sense for ANY type, be it record or Boolean.

Then we at least agree that they make sense for any composite type.

But please explain what use is a Boolean with discriminants.
I'm not sure...

>> In Ada
>> 9X, we allow them for any composite type except array types.  The
>> array-type restriction is for ease of implementation -- it does not
>> simplify the language nor make it easier to use.
>
> This is disputable. There exists numerous examples when disciminants for
> arrays were quite useful.

Agreed.

Dmitry, I think you misunderstood the quote.

It says that the RESTRICTION does not simplify or make easier to use.
(Restriction = arrays cannot have discrims.)  Too many double and triple
negatives there...

At the time, I thought arrays should be allowed to have discrims,
and tasks should, too.  Still think so.  "Ease of implementation"
referred to existing implementations of Ada 83, which of course did
not anticipate that array bounds are really discriminants in disguise.

- Bob



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 20:11                     ` Randy Brukardt
@ 2007-04-20 21:28                       ` Dmitry A. Kazakov
  2007-04-21  5:33                         ` Randy Brukardt
  2007-04-21  4:48                       ` unifying arrays and records (was Re: Rational for not making cursor tagged in Containers) Ray Blaak
  1 sibling, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-20 21:28 UTC (permalink / raw)


On Fri, 20 Apr 2007 15:11:53 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:1q1kx2jlcvnuj.ck0711mj4few$.dlg@40tude.net...
> ...
>> Also I fail to understand why polymorphic objects has to be records
>> and not arrays or access types. Why array or number cannot have
>> discriminants, but records can?
> 
> This ones easy. There is a fundamental difference between elementary types
> (which can represent only one value) and composite types (which can contain
> multiple values). Adding discriminants to an elementary type would turn it
> into a composite type -- and that way lies madness.

That's because you consider discriminant as a component. But why?
Discriminant is a constraint / parameter of a value. It is associated with
the value but is not necessarily a part of it.

Examples of discriminated scalar types:

1. type Ring_Buffer_Index (Size : Positive) is mod Size;

2. type Bounded_Integer (Min : Integer; Max : Integer) is range Min..Max;

3. type Dimensioned (Dimension : Unit) is digits 8 range -100.0..100.0;

4. type C_String (Length : Positive) is
       access all Interfaces.C.chars_array (1..Length);

Note the target is a flat array!

5. type Checked_Access (Not_Null : Boolean) is
       access not null (Not_Null) of Something;

The syntax is ugly, but I hope you got the idea.

> As far as why a polymorphic object has to be a record, that's simply because
> it is the most general composite type. It is a heterogeneous container.
> Indeed, I don't think I've ever implemented an abstraction as anything else
> (at least not for long); there is always a need for additional items beyond
> the main data.

Counter examples:

1. polymorphic access types (for smart pointers, interators, cursors) 

2, extensible enumeration types

3. polymorphic numeric types (mixed arithmetic implementations,
computations with mixed numeric representations)

> The better question is why there are arrays at all. A homogeneous container
> is by definition more limited than a heterogeneous one. So, the ideal
> language would find a way to completely unify arrays and records.

Yes, but first one should do something about static expressions. There is
no way to enforce keys of a record container to evaluate at compile-time.

> I suppose you could try to do something similar for elementary types (you
> can use special syntax if there is only one component in the container), but
> that would necessarily make programs fragile (adding a component would
> necessarily disallow that syntax, requiring massive changes).
> 
> So, I guess the ideal language would be one in which everything was a
> controlled record type. (For Janus/Ada, that's already true in many cases: a
> protected type is just a special controlled record type; task objects are
> essentially controlled, unconstrained arrays are really records that contain
> bounds and a data pointer, etc.) But such a language would be pretty
> space-inefficient (you could optimize individual calls to avoid dispatching,
> but there is no way to eliminate the space overhead, because you can never
> tell what might be done in some separately compiled unit.)

This is a consequence of IMO a wrong view on what discriminant (or tag) is.
If you consider them as components, you indeed land in the pitfall you
described above. But if discriminant is just an attribute of a value
forcibly removed when known static, then there is no any space loss. The
values of statically constrained / specific types will have no
discriminants / tags. Dynamically constrained / polymorphic values will
have it, just as dynamically constrained strings have a dope. Only the
[by-reference] types with the reserved words tagged or limited will have
discriminants and the tag among them stored the value. I think it is a
doable program.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 20:59                         ` Robert A Duff
@ 2007-04-20 22:14                           ` Dmitry A. Kazakov
  2007-04-23 17:38                             ` Adam Beneschan
  0 siblings, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-20 22:14 UTC (permalink / raw)


On Fri, 20 Apr 2007 16:59:02 -0400, Robert A Duff wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> Discriminants make sense for ANY type, be it record or Boolean.
> 
> Then we at least agree that they make sense for any composite type.

Yes.
 
> But please explain what use is a Boolean with discriminants.
> I'm not sure...

   type GUI_Boolean (Defined : Boolean := True) is (False, True);

When Defined = False, the value is rendered as blank and the user is forced
to enter it before it closes the dialog box.

(It is different from tri-state logical value (False, True, Uncertain),
because Defined describes the value itself, while Uncertain is just a value
among others.)

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 16:02               ` Jean-Pierre Rosen
@ 2007-04-21  2:53                 ` Anh Vo
  0 siblings, 0 replies; 66+ messages in thread
From: Anh Vo @ 2007-04-21  2:53 UTC (permalink / raw)


On Apr 20, 9:02 am, Jean-Pierre Rosen <r...@adalog.fr> wrote:
> Anh Vo a écrit :> On Apr 20, 4:59 am, Jean-Pierre Rosen <r...@adalog.fr> wrote:
> >> Anh Vo a écrit :> I do not understand what other confusions do you refer to. Other
> >>> advantage of prefix notation is that I do not have to fully qualify
> >>> nor apply use clause.
> >> And one advantage of use clause is that you don't have to use prefix
> >> notation ;-)
>
> > It is true. However, using use clause does not fit advantage category.
> > In addition, the side effect of using use clause, for most cases,
> > leans toward disadvantage side :-(
>
> A common opinion, but far from being universal (although voiced louder
> than the opposite).

It is the quality, not quantiy, that counts.

> For those of us who do not write Level-A software, use clauses increase
> readability, while keeping precise control over name space by opening
> visibility at the innermost level where it is needed.

I have to disagree with "use clauses increase readability" no matter
what kind of software written. Yes, it provides visibility so full
qualification is not needed.

> Of course, this assume that you use use clauses properly, and not after
> each with clause!

Certainly.

AV




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

* unifying arrays and records (was Re: Rational for not making cursor tagged in Containers)
  2007-04-20 20:11                     ` Randy Brukardt
  2007-04-20 21:28                       ` Dmitry A. Kazakov
@ 2007-04-21  4:48                       ` Ray Blaak
  1 sibling, 0 replies; 66+ messages in thread
From: Ray Blaak @ 2007-04-21  4:48 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:
> The better question is why there are arrays at all. A homogeneous container
> is by definition more limited than a heterogeneous one. So, the ideal
> language would find a way to completely unify arrays and records. Perhaps
> the array syntax would have to remain, but it would just be a language
> defined synonym for a record access.

Believe it or not, ECMAScript/JavaScript manages to do it.

obj.field is equivalent to obj["field"], like an implicit hashmap lookup.

obj[1] is just another lookup.

Now JavaScript is a wierd completely dynamic language. The kinds of games it
plays really relies on its non-staticness to work. It is actually closer to
Lisp rather than anything else, just with a Java-ish syntax, even down to its
functions being equivalent to full blown closures. It has nothing at all to do
with Java though.

I both hate it and love it at the same time.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 21:28                       ` Dmitry A. Kazakov
@ 2007-04-21  5:33                         ` Randy Brukardt
  2007-04-21  9:39                           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Randy Brukardt @ 2007-04-21  5:33 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:desawg9du795$.1nlp3h75ktl4a.dlg@40tude.net...
> On Fri, 20 Apr 2007 15:11:53 -0500, Randy Brukardt wrote:
>
> > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> > news:1q1kx2jlcvnuj.ck0711mj4few$.dlg@40tude.net...
> > ...
> >> Also I fail to understand why polymorphic objects has to be records
> >> and not arrays or access types. Why array or number cannot have
> >> discriminants, but records can?
> >
> > This ones easy. There is a fundamental difference between elementary
types
> > (which can represent only one value) and composite types (which can
contain
> > multiple values). Adding discriminants to an elementary type would turn
it
> > into a composite type -- and that way lies madness.
>
> That's because you consider discriminant as a component. But why?
> Discriminant is a constraint / parameter of a value. It is associated with
> the value but is not necessarily a part of it.

That way lies madness. You could have the same value yet they wouldn't pass
the checks because this stuff that isn't part of the value doesn't match.
That's very different than a range constraint, for instance, which is
outside the value, but it doesn't change the checking of the value. That is,
values don't have constraints.

> Examples of discriminated scalar types:
>
> 1. type Ring_Buffer_Index (Size : Positive) is mod Size;
>
> 2. type Bounded_Integer (Min : Integer; Max : Integer) is range Min..Max;

These would be possible in Ada (as records) if there wasn't a rule
specifically forbidding it. And the reason for the rule is simply that there
isn't any real value to these sorts of constructs. even if there was,
though, mapping them as records, assuming a decent way to handle literals.
No reason to treat them as elementary.

> 3. type Dimensioned (Dimension : Unit) is digits 8 range -100.0..100.0;

Same here.

> 4. type C_String (Length : Positive) is
>        access all Interfaces.C.chars_array (1..Length);
>
> Note the target is a flat array!
>
> 5. type Checked_Access (Not_Null : Boolean) is
>        access not null (Not_Null) of Something;

All constrained access types are madness. It isn't possible to make any
useful meaning out of them, and they cause an infinite number of
definitional problems. Ada shouldn't have ever had them (we've essentially
made them illegal for general access types, but we can't do anything about
the Ada 83 ones).

In any case, *my* language would de-emphisize access types as much as
possible. No anonymous ones; probably structural matching (so the named ones
would work a lot like the anonymous ones of Ada); in out parameters serve
the purpose better anyway. They'd be second-class citizens to discourage
their use by anyone other than people implementing containers...

...
> Counter examples:
>
> 1. polymorphic access types (for smart pointers, interators, cursors)

No anything for access types; they should be made so hard to use that it's
almost unthinkable to do so. All of the things you mention are ADTs,
implemented by controlled records. (Dereference would also be a possible
redefinable record operation, of course.)

Yes, you'll occassionally need access types to implement ADTs, but never,
ever visibly in a spec.

> 2, extensible enumeration types

We tried to work this out, and it simply doesn't work. Operations like
ordering simply aren't extensible in a useful way.

> 3. polymorphic numeric types (mixed arithmetic implementations,
> computations with mixed numeric representations)

Maybe, but I'm dubious. Again, I think it would be better to have better
ADTs that could replace a numeric type.

...
> > So, I guess the ideal language would be one in which everything was a
> > controlled record type. (For Janus/Ada, that's already true in many
cases: a
> > protected type is just a special controlled record type; task objects
are
> > essentially controlled, unconstrained arrays are really records that
contain
> > bounds and a data pointer, etc.) But such a language would be pretty
> > space-inefficient (you could optimize individual calls to avoid
dispatching,
> > but there is no way to eliminate the space overhead, because you can
never
> > tell what might be done in some separately compiled unit.)
>
> This is a consequence of IMO a wrong view on what discriminant (or tag)
is.
> If you consider them as components, you indeed land in the pitfall you
> described above. But if discriminant is just an attribute of a value
> forcibly removed when known static, then there is no any space loss.

These are almost never known to be static (consider parameter passing). What
you're suggesting *might* be possible to describe, but it wouldn't be
possible to implement. If the parameter passing code in Janus/Ada got any
more complex, it could never be made to work (it might already be at that
point - there's over 2500 lines of code for that alone).

> The values of statically constrained / specific types will have no
> discriminants / tags. Dynamically constrained / polymorphic values will
> have it, just as dynamically constrained strings have a dope. Only the
> [by-reference] types with the reserved words tagged or limited will have
> discriminants and the tag among them stored the value. I think it is a
> doable program.

Maybe, but only if you're successful in getting rid of generics and most of
the other special cases (like "view conversions"). Otherwise, it is just too
complex to implement. And if you do get rid of generics, I think you'll find
that nothing significant is ever known to be static.

                               Randy.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 20:44                       ` Robert A Duff
@ 2007-04-21  5:38                         ` Randy Brukardt
  2007-04-22  1:14                           ` Robert A Duff
  0 siblings, 1 reply; 66+ messages in thread
From: Randy Brukardt @ 2007-04-21  5:38 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wccbqhizsh0.fsf@shell01.TheWorld.com...
...
> I also thought (and continue to think) that array types should be
> allowed to have discriminants.  The quote above was a jab at people
> who thought otherwise.  I lost that argument.

That would have been me. I think I was arguing simply from the
implementation complexity standpoint (my comment to Dmitry about the amount
of code needed to implement parameter passing would be a lot worse with this
capability). I think your argument was that such things should just be
implemented as records, but that leads to the explosion of possibilities
(now every array might be implemented in a number of new ways on top of the
old ways). I'm not sure I'd make that argument again. (I know I wouldn't be
against 'in out' parameters in functions again. The use of access types to
replace them is disgusting.)

                                       Randy.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-21  5:33                         ` Randy Brukardt
@ 2007-04-21  9:39                           ` Dmitry A. Kazakov
  2007-04-22  4:28                             ` Randy Brukardt
  0 siblings, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-21  9:39 UTC (permalink / raw)


On Sat, 21 Apr 2007 00:33:12 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:desawg9du795$.1nlp3h75ktl4a.dlg@40tude.net...
>> On Fri, 20 Apr 2007 15:11:53 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:1q1kx2jlcvnuj.ck0711mj4few$.dlg@40tude.net...
>>> ...
>>>> Also I fail to understand why polymorphic objects has to be records
>>>> and not arrays or access types. Why array or number cannot have
>>>> discriminants, but records can?
>>>
>>> This ones easy. There is a fundamental difference between elementary types
>>> (which can represent only one value) and composite types (which can contain
>>> multiple values). Adding discriminants to an elementary type would turn it
>>> into a composite type -- and that way lies madness.
>>
>> That's because you consider discriminant as a component. But why?
>> Discriminant is a constraint / parameter of a value. It is associated with
>> the value but is not necessarily a part of it.
> 
> That way lies madness. You could have the same value yet they wouldn't pass
> the checks because this stuff that isn't part of the value doesn't match.

Sure, example: access discriminants of task types.

It is not madness, it is the same difference like between class-wide and
specific. These are different though mutually compatible [sub]types. A
dynamically constrained value has discriminants, a statically constrained
value does not have the discriminants whose values are statically known.
Even if these are still kept in the value bit pattern. Known discriminants
are undeterminable from constrained values [for sanity reasons].

> That's very different than a range constraint, for instance, which is
> outside the value, but it doesn't change the checking of the value. That is,
> values don't have constraints.

The values are not same, String is not String (1..80).

>> Examples of discriminated scalar types:
>>
>> 1. type Ring_Buffer_Index (Size : Positive) is mod Size;
>>
>> 2. type Bounded_Integer (Min : Integer; Max : Integer) is range Min..Max;
> 
> These would be possible in Ada (as records) if there wasn't a rule
> specifically forbidding it. And the reason for the rule is simply that there
> isn't any real value to these sorts of constructs. even if there was,
> though, mapping them as records, assuming a decent way to handle literals.

If Ring_Buffer_Index (being privately a record) can be used as an array
index then it is just fine to me.

> No reason to treat them as elementary.

Hmm, what is the difference between elementary and non-elementary? In which
way mod 256 is more elementary than array (Positive range 1..8) of Boolean?
To me the only difference is built-in vs. user-defined, which vanishes in
absence of visibility on the private declarations.

>> 3. type Dimensioned (Dimension : Unit) is digits 8 range -100.0..100.0;
> 
> Same here.

But it is the only way to have dimensioned values in a usable way.

>> 4. type C_String (Length : Positive) is
>>        access all Interfaces.C.chars_array (1..Length);
>>
>> Note the target is a flat array!
>>
>> 5. type Checked_Access (Not_Null : Boolean) is
>>        access not null (Not_Null) of Something;
> 
> All constrained access types are madness.
[...]
> ...
>> Counter examples:
>>
>> 1. polymorphic access types (for smart pointers, interators, cursors)
> 
> No anything for access types; they should be made so hard to use that it's
> almost unthinkable to do so. All of the things you mention are ADTs,
> implemented by controlled records. (Dereference would also be a possible
> redefinable record operation, of course.)
> 
> Yes, you'll occassionally need access types to implement ADTs, but never,
> ever visibly in a spec.

Then we are in full agreement. All access types above are just
abbreviations for the [record, whatever] types implementing access
interface. This implementation does not bother me, as long as I can ensure
its efficiency.

What I want is a uniform way to hang a constraint on anything regardless on
where that thing will be used. No special treatment to any interface.

>> 2, extensible enumeration types
> 
> We tried to work this out, and it simply doesn't work. Operations like
> ordering simply aren't extensible in a useful way.

You mean 'Succ? That should depend on covariance/contravariance of the
arguments and the result. If you consider constrained and unconstrained
values as same, then I bet there is no solution. The compiler shall know
the difference when an enumeration value appears in a case-statement.

>> 3. polymorphic numeric types (mixed arithmetic implementations,
>> computations with mixed numeric representations)
> 
> Maybe, but I'm dubious. Again, I think it would be better to have better
> ADTs that could replace a numeric type.

Full agreement as above.

> ...
>>> So, I guess the ideal language would be one in which everything was a
>>> controlled record type. (For Janus/Ada, that's already true in many cases: a
>>> protected type is just a special controlled record type; task objects are
>>> essentially controlled, unconstrained arrays are really records that contain
>>> bounds and a data pointer, etc.) But such a language would be pretty
>>> space-inefficient (you could optimize individual calls to avoid dispatching,
>>> but there is no way to eliminate the space overhead, because you can never
>>> tell what might be done in some separately compiled unit.)
>>
>> This is a consequence of IMO a wrong view on what discriminant (or tag) is.
>> If you consider them as components, you indeed land in the pitfall you
>> described above. But if discriminant is just an attribute of a value
>> forcibly removed when known static, then there is no any space loss.
> 
> These are almost never known to be static (consider parameter passing).

Because presently discriminants are not allowed, so, I presume, they are
all static. I.e. it definitely works! (:-))

> What
> you're suggesting *might* be possible to describe, but it wouldn't be
> possible to implement. If the parameter passing code in Janus/Ada got any
> more complex, it could never be made to work (it might already be at that
> point - there's over 2500 lines of code for that alone).

Just 2500? (:-))

>> The values of statically constrained / specific types will have no
>> discriminants / tags. Dynamically constrained / polymorphic values will
>> have it, just as dynamically constrained strings have a dope. Only the
>> [by-reference] types with the reserved words tagged or limited will have
>> discriminants and the tag among them stored the value. I think it is a
>> doable program.
> 
> Maybe, but only if you're successful in getting rid of generics

If no new formal generic types will be introduced, then I don't see it as a
big deal. Possibly generics will never be get right, but that is not
because of discriminants. (:-))

> and most of
> the other special cases (like "view conversions").

No view conversions for non-by-reference types, a new object will be
created instead.

> Otherwise, it is just too
> complex to implement. And if you do get rid of generics, I think you'll find
> that nothing significant is ever known to be static.

Generics is a sufficiently different thing. The constraint is put on the
compilation unit like package and then it propagates to the declarations of
the unit. The closest approximation is derivation, which puts tag
constraint on a class-wide. It would be interesting to analyse some
large-scale Ada code. I guess that less than 10% of all calls with tagged
arguments would be dispatching. I.e. 90% is static.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-21  5:38                         ` Randy Brukardt
@ 2007-04-22  1:14                           ` Robert A Duff
  2007-04-22  4:08                             ` Randy Brukardt
  0 siblings, 1 reply; 66+ messages in thread
From: Robert A Duff @ 2007-04-22  1:14 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
> news:wccbqhizsh0.fsf@shell01.TheWorld.com...
> ...
>> I also thought (and continue to think) that array types should be
>> allowed to have discriminants.  The quote above was a jab at people
>> who thought otherwise.  I lost that argument.
>
> That would have been me. I think I was arguing simply from the
> implementation complexity standpoint

Implementation complexity for existing (Ada 83) implementations.
A newly-designed implementation would have had no trouble.
20-20 hindsight!

I claim that it's much easier to implement Ada 95 than it is to
implement Ada 83 and then adapt that implementation to Ada 95.

The same applies to 95/2005.  I sweated blood implementing the AI-318
features (limited constructor functions) for Ada 2005 in GNAT, but I'm
pretty sure that AI-318 would be no extra trouble in a from-scratch
implementation of Ada 2005.

>... (my comment to Dmitry about the amount
> of code needed to implement parameter passing would be a lot worse with this
> capability). I think your argument was that such things should just be
> implemented as records, but that leads to the explosion of possibilities
> (now every array might be implemented in a number of new ways on top of the
> old ways). I'm not sure I'd make that argument again. (I know I wouldn't be
> against 'in out' parameters in functions again. The use of access types to
> replace them is disgusting.)

Agreed.

- Bob



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-22  1:14                           ` Robert A Duff
@ 2007-04-22  4:08                             ` Randy Brukardt
  0 siblings, 0 replies; 66+ messages in thread
From: Randy Brukardt @ 2007-04-22  4:08 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
news:wcc8xclrz1j.fsf@shell01.TheWorld.com...
> "Randy Brukardt" <randy@rrsoftware.com> writes:
>
> > "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message
> > news:wccbqhizsh0.fsf@shell01.TheWorld.com...
> > ...
> >> I also thought (and continue to think) that array types should be
> >> allowed to have discriminants.  The quote above was a jab at people
> >> who thought otherwise.  I lost that argument.
> >
> > That would have been me. I think I was arguing simply from the
> > implementation complexity standpoint
>
> Implementation complexity for existing (Ada 83) implementations.
> A newly-designed implementation would have had no trouble.
> 20-20 hindsight!

That's probably true, but there were almost no new implementations. I think
GNAT was the only one. We forked our compiler, but we certainly did not
start from scratch. Implementing expression resolution once was enough (by
far!).

> I claim that it's much easier to implement Ada 95 than it is to
> implement Ada 83 and then adapt that implementation to Ada 95.

That has to be true, simply because there are rules in Ada 83 that don't
exist in Ada 95; clearly there is an effort to support those rules. But I
don't think it matters in any important practical way; most everything was
an addition, not a change.

> The same applies to 95/2005.  I sweated blood implementing the AI-318
> features (limited constructor functions) for Ada 2005 in GNAT, but I'm
> pretty sure that AI-318 would be no extra trouble in a from-scratch
> implementation of Ada 2005.

I suspect that you are being kind; it would be an amazing amount of work
either way. Passing finalization chains, task masters, and *moving* them is
outside of the normal intent in any language design - finalization chains
are pretty much the only way to implement that, no matter what bizarre
requirements are added in unusual cases. (My intent is simply to add a
number of new calling (sub)conventions; the only issue is if they are used
for any existing subprograms written in assembler. But those new conventions
will take a lot of work to make them work properly.) But the big gain in not
implementing Ada 95 would not be implementing all of that hair-brained
return-by-reference stuff.

                      Randy.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-21  9:39                           ` Dmitry A. Kazakov
@ 2007-04-22  4:28                             ` Randy Brukardt
  2007-04-22  8:38                               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Randy Brukardt @ 2007-04-22  4:28 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:15dj4pbkifj9c$.1g4y21vyx4j4d$.dlg@40tude.net...
> On Sat, 21 Apr 2007 00:33:12 -0500, Randy Brukardt wrote:
>
> > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
...
> >> That's because you consider discriminant as a component. But why?
> >> Discriminant is a constraint / parameter of a value. It is associated
with
> >> the value but is not necessarily a part of it.
> >
> > That way lies madness. You could have the same value yet they wouldn't
pass
> > the checks because this stuff that isn't part of the value doesn't
match.
>
> Sure, example: access discriminants of task types.

Huh? Two tasks never have the same value.

> It is not madness, it is the same difference like between class-wide and
> specific. These are different though mutually compatible [sub]types. A
> dynamically constrained value has discriminants, a statically constrained
> value does not have the discriminants whose values are statically known.
> Even if these are still kept in the value bit pattern. Known discriminants
> are undeterminable from constrained values [for sanity reasons].

Huh again? You have to know the discriminants, or you couldn't pass them to
an unconstrained (or, if you prefer, 'Class) parameter.

> > That's very different than a range constraint, for instance, which is
> > outside the value, but it doesn't change the checking of the value. That
is,
> > values don't have constraints.
>
> The values are not same, String is not String (1..80).

String is a type, not a value. String(1..80) is a subtype, not value. "ABC"
is a value and that value includes its bounds.

...
> Hmm, what is the difference between elementary and non-elementary? In
which
> way mod 256 is more elementary than array (Positive range 1..8) of
Boolean?

One is a single value, the other is a set of values. You can do math on the
former to extract bits, but you can't get at them directly.

Surely, you could design a language with only kind of type (a super-record).
But it would be highly inefficient; there'd be a few special cases that
could be fast, but they wouldn't happen that much.

> To me the only difference is built-in vs. user-defined, which vanishes in
> absence of visibility on the private declarations.
...
> > ...
> >>> So, I guess the ideal language would be one in which everything was a
> >>> controlled record type. (For Janus/Ada, that's already true in many
cases: a
> >>> protected type is just a special controlled record type; task objects
are
> >>> essentially controlled, unconstrained arrays are really records that
contain
> >>> bounds and a data pointer, etc.) But such a language would be pretty
> >>> space-inefficient (you could optimize individual calls to avoid
dispatching,
> >>> but there is no way to eliminate the space overhead, because you can
never
> >>> tell what might be done in some separately compiled unit.)
> >>
> >> This is a consequence of IMO a wrong view on what discriminant (or tag)
is.
> >> If you consider them as components, you indeed land in the pitfall you
> >> described above. But if discriminant is just an attribute of a value
> >> forcibly removed when known static, then there is no any space loss.
> >
> > These are almost never known to be static (consider parameter passing).
>
> Because presently discriminants are not allowed, so, I presume, they are
> all static. I.e. it definitely works! (:-))

Discriminants are not allowed where? I was talking about where they are
allowed; if you extend them to be allowed everywhere. Of course, a compiler
could special case no possible discriminants (I think it would have to,
adding a complexity). But if you allow adding them to extensions (and it
seems you should), then not 'Class ever is known to not have discriminants.
So they're almost always dynamic, and they have to almost always be part of
the value. (And there are a lot more uses of 'Class in your universe without
generics!)

> > What
> > you're suggesting *might* be possible to describe, but it wouldn't be
> > possible to implement. If the parameter passing code in Janus/Ada got
any
> > more complex, it could never be made to work (it might already be at
that
> > point - there's over 2500 lines of code for that alone).
>
> Just 2500? (:-))

Parameter passing is one of the easiest (conceptually) things that a
compiler has to do. It's just evaluate and push. For that to get that
complex is outrageous. (Yes, our shared generics are a major culprit.)

> >> The values of statically constrained / specific types will have no
> >> discriminants / tags. Dynamically constrained / polymorphic values will
> >> have it, just as dynamically constrained strings have a dope. Only the
> >> [by-reference] types with the reserved words tagged or limited will
have
> >> discriminants and the tag among them stored the value. I think it is a
> >> doable program.
> >
> > Maybe, but only if you're successful in getting rid of generics
>
> If no new formal generic types will be introduced, then I don't see it as
a
> big deal. Possibly generics will never be get right, but that is not
> because of discriminants. (:-))

If you do shared generics as we do, generics essentially double the work for
everything. You idea would multiply it by 4 again. I think that's beyond my
ability to imagine...

...
> > Otherwise, it is just too
> > complex to implement. And if you do get rid of generics, I think you'll
find
> > that nothing significant is ever known to be static.
>
> Generics is a sufficiently different thing. The constraint is put on the
> compilation unit like package and then it propagates to the declarations
of
> the unit. The closest approximation is derivation, which puts tag
> constraint on a class-wide. It would be interesting to analyse some
> large-scale Ada code. I guess that less than 10% of all calls with tagged
> arguments would be dispatching. I.e. 90% is static.

It might even be less than that. But I was referring to your previous
comments on how lousy generics are in a general way. I was presuming that
your ideal language would not have them. But then you'd have to have a lot
of operations on 'Class (to get a polymorphic Put, for one example). In
which case there would be far more dispatching calls than in Ada (we tend to
use generics rather than inheritance, I think).

                              Randy.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-22  4:28                             ` Randy Brukardt
@ 2007-04-22  8:38                               ` Dmitry A. Kazakov
  2007-04-23 23:26                                 ` Randy Brukardt
  2007-04-24  8:58                                 ` Georg Bauhaus
  0 siblings, 2 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-22  8:38 UTC (permalink / raw)


On Sat, 21 Apr 2007 23:28:34 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:15dj4pbkifj9c$.1g4y21vyx4j4d$.dlg@40tude.net...
>> On Sat, 21 Apr 2007 00:33:12 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> ...
>>>> That's because you consider discriminant as a component. But why?
>>>> Discriminant is a constraint / parameter of a value. It is associated with
>>>> the value but is not necessarily a part of it.
>>>
>>> That way lies madness. You could have the same value yet they wouldn't pass
>>> the checks because this stuff that isn't part of the value doesn't match.
>>
>> Sure, example: access discriminants of task types.
> 
> Huh? Two tasks never have the same value.

So how are you going to check the discriminant once, provided that the
value shall determine the validity? My point is that there are two values
of different types we are talking about, one with and another without the
discriminant.

>> It is not madness, it is the same difference like between class-wide and
>> specific. These are different though mutually compatible [sub]types. A
>> dynamically constrained value has discriminants, a statically constrained
>> value does not have the discriminants whose values are statically known.
>> Even if these are still kept in the value bit pattern. Known discriminants
>> are undeterminable from constrained values [for sanity reasons].
> 
> Huh again? You have to know the discriminants, or you couldn't pass them to
> an unconstrained (or, if you prefer, 'Class) parameter.

Where is any problem? If the discriminant is statically determinable I can
reconstruct it at the call point, create a dynamically constrained object
[which is not necessarily contiguous in the memory] and pass it. If the
discriminant is indeterminable, then I must already have a dynamically
constrained object to pass.

>>> That's very different than a range constraint, for instance, which is
>>> outside the value, but it doesn't change the checking of the value. That is,
>>> values don't have constraints.
>>
>> The values are not same, String is not String (1..80).
> 
> String is a type, not a value. String(1..80) is a subtype, not value. "ABC"
> is a value and that value includes its bounds.

No, that depends on the type of "ABC". What is "ABC"'First? There is no
logical way to derive it from the value otherwise than voluntarily set it
at some arbitrary value, like 1.

> ...
>> Hmm, what is the difference between elementary and non-elementary? In which
>> way mod 256 is more elementary than array (Positive range 1..8) of Boolean?
> 
> One is a single value, the other is a set of values. You can do math on the
> former to extract bits, but you can't get at them directly.

Neither I can do it with the latter. There is an operation which extracts
bits from the value. This operation has the parameter of some other type
and the result of third. I could define such operation on the former or
disallow it on the latter making the type private. Would that change its
elementariness? Just per view? Wouldn't F'Exponent make F non-elementary?
What about Boolean xor? May I claim that xor extracts a component of its
first Boolean argument in some Platonic universe? It just makes no sense to
me.

>> Because presently discriminants are not allowed, so, I presume, they are
>> all static. I.e. it definitely works! (:-))
> 
> Discriminants are not allowed where? I was talking about where they are
> allowed; if you extend them to be allowed everywhere.

Yes, I meant that nothing would change for the types which presently have
no discriminants, if we allowed but not used them.

> Of course, a compiler
> could special case no possible discriminants (I think it would have to,
> adding a complexity). But if you allow adding them to extensions (and it
> seems you should), then not 'Class ever is known to not have discriminants.

'Class is a difficult case. And a general question regarding it is, should
it be possible to have it "hyper-dispatching"? [sorry, for inventing new
terms on the fly]? I mean T'Class'Class. If yes, then we will have
different levels of tags. Another question is whether
"multiple-polymorphic" things were allowed. Here I mean multiple of tags at
the same level: T'Class(1), T'Class(2) etc.

I think these questions have to be answered in order to build a sane OO
types system. What I do believe is that this system could be uniformly
expressed in terms discriminants and impose no *any* penalty on computing
with specific types.

> So they're almost always dynamic, and they have to almost always be part of
> the value. (And there are a lot more uses of 'Class in your universe without
> generics!)

Yes, T'Class always has the tag (which is not necessarily dynamic).
 
>>>> The values of statically constrained / specific types will have no
>>>> discriminants / tags. Dynamically constrained / polymorphic values will
>>>> have it, just as dynamically constrained strings have a dope. Only the
>>>> [by-reference] types with the reserved words tagged or limited will have
>>>> discriminants and the tag among them stored the value. I think it is a
>>>> doable program.
>>>
>>> Maybe, but only if you're successful in getting rid of generics
>>
>> If no new formal generic types will be introduced, then I don't see it as a
>> big deal. Possibly generics will never be get right, but that is not
>> because of discriminants. (:-))
> 
> If you do shared generics as we do, generics essentially double the work for
> everything. You idea would multiply it by 4 again. I think that's beyond my
> ability to imagine...

It is not obvious to me. I guess that "type X is new Y with private" is
where it should stop. Certainly, I don't want to try to express the types
constraints in formal generic parameters. It would be a Sisyphean task
worth of nothing.

> But I was referring to your previous
> comments on how lousy generics are in a general way. I was presuming that
> your ideal language would not have them. But then you'd have to have a lot
> of operations on 'Class (to get a polymorphic Put, for one example). In
> which case there would be far more dispatching calls than in Ada (we tend to
> use generics rather than inheritance, I think).

Certainly, but I guess that shared generic bodies have to "dispatch" to the
actual "with procedure" as well. In the end it should turn equivalent,
because, there is no implicit re-dispatch in Ada.

If the class-wide bodies are inlined, then in comparable cases the tags
will be known and all dispatching calls within them will be resolved
statically. The rest would be space overhead for storing tags. Now, if the
callee are inlined as well and type involved is not by-reference, then the
compiler can remove call T -> T'Class -> T conversions, it would otherwise
generate. That would mean no any overhead.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 19:55                       ` Randy Brukardt
@ 2007-04-22  9:54                         ` Georg Bauhaus
  2007-04-22 11:19                           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Georg Bauhaus @ 2007-04-22  9:54 UTC (permalink / raw)


On Fri, 2007-04-20 at 14:55 -0500, Randy Brukardt wrote: 
> "Georg Bauhaus" <bauhaus@futureapps.de> wrote in message
> news:1177097829.26685.36.camel@localhost.localdomain...
> ...
> > By analogy, and consistent with the desired record interfaces,
> > I will be asking for task type interfaces (no, not really).
> 
> Ada already has task interfaces, so you don't need to ask. ;-)

I meant something different (i.e. not synchronized interfaces),
based on my initial understanding that the concept of record
was to be changed, not that there be some publicly visible
syntactic sugar for read/write access to private components.

If the suggested "record interface" allows programmers to write
a subprogram that defines what R.A means, then the analog
*change* for task types will be "type T is interface task ...".
It will allow programmers to specify what "accessing"
The_T.A means, i.e. they not only write an acceptor A, but they
will also be writing what "accept" means. Only be default
will "accept" fall back to the LRM thing. :-)

Now the argument was that in a sense I can write "callable
components" of packages, of protected objects, of tasks, but
not of simple composite types. If this distinction seems
unwarranted, it is perhaps interesting to compare with
Eiffel counterparts. ECMA Eiffel defines Dmitry's suggestion
AFAICS. (I'll leave out the complication introduced by expanded
objects.) Access to a record component in Eiffel is either a
function or looks like a function, depending on how it is
defined. A client writing a record component in Eiffel will
always call a procedure of the record class, even when it
is written like assignment (":="), because the only way to modify
an object from the outside is to call a procedure. The function
will have an assigner command associated with it,

class FOO inherit FLOAT
feature
   get: INTEGER assign put is ...
   put (Value: INTEGER) is ...

Suppose Ada was to give up simple record component read/write
in favor of programmer defined subprograms implementing record
interfaces. There are cases when the translated code will have
to move memory words from here to their (as per LRM and reps.)
When this is to be done for an Eiffel record, then reportedly,
it always is tricky. Either the Eiffel literature 
suggest that the compiler has built in magic, or you revert
to the programmer's knowledge of how the Eiffel code is
translated to C and have him use this C knowledge to achieve the
desired effect (assignment) at the C level.



> Shouldn't it be possible
> to create a complete abstraction that works like the built-in ones?

Yes and No. I had (mis)understood that the built-in "abstractions"
like "record" should only default to built-in mechanics. The more basic
new "record interface" mechanism would in fact be less basic, because
programmers can write a subprogram for what .Integer_Component := 5;
will mean. If this were the only mechanism, wouldn't we soon be
entering an infinite loop of a missing basic assignment? For what
is the reason that I cannot make Integer assignment be an interface
;-) ;-)


> After all, it's not about the syntax:
> 
>    X := Y;
> 
> looks simple, but I've had to debug as much as 1K of machine code that
> actually implements it. There can be a lot of complexity hidden behind the
> two characters ":=". There is no reason to think that it would be a problem
> if '.' or '(' or '"' had similar complexity. (Indeed, there are cases where
> they do, you just can't write such cases yourself.)

Exactly, and I was trying to suggest that it might or might not
be a good idea to have the programmers write such cases, as they
will have to manage the complexity of assignment in a way that
is likely more complex than understanding ":=".
  But then, I think Dmitry is basically suggesting different
syntax, not a new record mechanism; after all, with tagged
records and Controlled components, the call side syntax is almost
part of Ada.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-22  9:54                         ` Georg Bauhaus
@ 2007-04-22 11:19                           ` Dmitry A. Kazakov
  0 siblings, 0 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-22 11:19 UTC (permalink / raw)


On Sun, 22 Apr 2007 11:54:34 +0200, Georg Bauhaus wrote:

> If the suggested "record interface" allows programmers to write
> a subprogram that defines what R.A means, then the analog
> *change* for task types will be "type T is interface task ...".
> It will allow programmers to specify what "accessing"
> The_T.A means, i.e. they not only write an acceptor A, but they
> will also be writing what "accept" means. Only be default
> will "accept" fall back to the LRM thing. :-)

Unfortunately that won't work, because "accept" is an implementation, but
interface. A better example of what, I guess, you meant, could be
"selectable interface" for entries, which would define the behavior of the
select statements. But again, unfortunately, there is no obvious way to
abstract the meaning of from the implementation of. The meaning of
concurrency constructs seem to be non-functional... Digressing, I would
guess that there might be fundamental reasons about it.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-20 22:14                           ` Dmitry A. Kazakov
@ 2007-04-23 17:38                             ` Adam Beneschan
  2007-04-23 19:18                               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Adam Beneschan @ 2007-04-23 17:38 UTC (permalink / raw)


On Apr 20, 3:14 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> > But please explain what use is a Boolean with discriminants.
> > I'm not sure...
>
>    type GUI_Boolean (Defined : Boolean := True) is (False, True);
>
> When Defined = False, the value is rendered as blank and the user is forced
> to enter it before it closes the dialog box.

X, Y : GUI_Boolean;

If you say X = Y, does it compare just the values, or does it compare
the discriminants also?

If it compares the discriminants, what do you write when you want to
compare just the values, without caring what the discriminants happen
to be?

What does "X = True" mean?  Does X.Defined have any effect on the
value of this expression?

OK, X is a GUI_Boolean that has Defined=false.  You now want to create
Y to be a GUI_Boolean that has the same value as X but Defined=true.
How do you write that, given that Ada does not let you put a
discriminant on the left side of an assignment?

There are lots of syntactic and semantic issues involved with sticking
a discriminant on a scalar that you probably haven't thought through.
I agree with Randy---that way lies madness, or at the very least a
severe migraine.  Thank you, but I think I'll stick to

    type My_Boolean_Value is (False, True);
    type GUI_Boolean (Defined : Boolean := True) is record
        Val : My_Boolean_Value;
    end record;

At least I know what I'm doing if I use this type.  If X is a
GUI_Boolean, then X refers to the whole record and X.Val refers to
just the value.  Nice, simple, easy to understand.

                                   -- Adam





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-23 17:38                             ` Adam Beneschan
@ 2007-04-23 19:18                               ` Dmitry A. Kazakov
  2007-04-24  0:15                                 ` Adam Beneschan
  0 siblings, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-23 19:18 UTC (permalink / raw)


On 23 Apr 2007 10:38:06 -0700, Adam Beneschan wrote:

> On Apr 20, 3:14 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>>> But please explain what use is a Boolean with discriminants.
>>> I'm not sure...
>>
>>    type GUI_Boolean (Defined : Boolean := True) is (False, True);
>>
>> When Defined = False, the value is rendered as blank and the user is forced
>> to enter it before it closes the dialog box.
> 
> X, Y : GUI_Boolean;
> 
> If you say X = Y, does it compare just the values, or does it compare
> the discriminants also?

That depends on how equality operation were defined for the given type. In
the concrete case of GUI_Boolean, the user-defined "=" would raise
Constraint_Error if at least one of the discriminants is false. There will
be probably another private equivalence defined for the containers of
GUI_Boolean.

> If it compares the discriminants, what do you write when you want to
> compare just the values, without caring what the discriminants happen
> to be?

It is the programmer's business to define correct "=". Ada has no
responsibility to generate semantically correct equality.

> What does "X = True" mean?  Does X.Defined have any effect on the
> value of this expression?
> 
> OK, X is a GUI_Boolean that has Defined=false.  You now want to create
> Y to be a GUI_Boolean that has the same value as X but Defined=true.

This is semantically wrong for GUI_Boolean. An undefined value has no
defined value...

> How do you write that, given that Ada does not let you put a
> discriminant on the left side of an assignment?

How do you change Float'Fraction of a Float X keeping the value of X same?
How do you change X'Length without changing the value of X?
Why should I write such things?

> There are lots of syntactic and semantic issues involved with sticking
> a discriminant on a scalar that you probably haven't thought through.

All these problems were solved for the type String. In general, the
problems you have referred equally apply to attributes of values. Ada has
lots of attributes of values, whether scalar or not. That never was a
problem.

> I agree with Randy---that way lies madness, or at the very least a
> severe migraine.  Thank you, but I think I'll stick to
> 
>     type My_Boolean_Value is (False, True);
>     type GUI_Boolean (Defined : Boolean := True) is record
>         Val : My_Boolean_Value;
>     end record;
> 
> At least I know what I'm doing if I use this type.  If X is a
> GUI_Boolean, then X refers to the whole record and X.Val refers to
> just the value.  Nice, simple, easy to understand.

To have a public discriminant has nothing to do with being implemented as a
record. And reverse.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-22  8:38                               ` Dmitry A. Kazakov
@ 2007-04-23 23:26                                 ` Randy Brukardt
  2007-04-24 10:43                                   ` Dmitry A. Kazakov
  2007-04-24  8:58                                 ` Georg Bauhaus
  1 sibling, 1 reply; 66+ messages in thread
From: Randy Brukardt @ 2007-04-23 23:26 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:1q5s2gqbzhatf$.2xu8gdz4hxm8$.dlg@40tude.net...
> On Sat, 21 Apr 2007 23:28:34 -0500, Randy Brukardt wrote:
>
> > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> > news:15dj4pbkifj9c$.1g4y21vyx4j4d$.dlg@40tude.net...
> >> On Sat, 21 Apr 2007 00:33:12 -0500, Randy Brukardt wrote:
> >>
> >>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> > ...
> >>>> That's because you consider discriminant as a component. But why?
> >>>> Discriminant is a constraint / parameter of a value. It is associated
with
> >>>> the value but is not necessarily a part of it.
> >>>
> >>> That way lies madness. You could have the same value yet they wouldn't
pass
> >>> the checks because this stuff that isn't part of the value doesn't
match.
> >>
> >> Sure, example: access discriminants of task types.
> >
> > Huh? Two tasks never have the same value.
>
> So how are you going to check the discriminant once, provided that the
> value shall determine the validity? My point is that there are two values
> of different types we are talking about, one with and another without the
> discriminant.

I'm sorry, but I have no idea of what you are talking about at this point. I
think our discussion has gotten two abstract, and precisely what is being
proposed is no longer obvious...

> >> It is not madness, it is the same difference like between class-wide
and
> >> specific. These are different though mutually compatible [sub]types. A
> >> dynamically constrained value has discriminants, a statically
constrained
> >> value does not have the discriminants whose values are statically
known.
> >> Even if these are still kept in the value bit pattern. Known
discriminants
> >> are undeterminable from constrained values [for sanity reasons].
> >
> > Huh again? You have to know the discriminants, or you couldn't pass them
to
> > an unconstrained (or, if you prefer, 'Class) parameter.
>
> Where is any problem? If the discriminant is statically determinable I can
> reconstruct it at the call point, create a dynamically constrained object
> [which is not necessarily contiguous in the memory] and pass it. If the
> discriminant is indeterminable, then I must already have a dynamically
> constrained object to pass.

You said "Known discriminants are undeterminable from constrained values
[for sanity reasons]." So where else do they come from? The type of the
value contains no information (they're always unconstrained); the subtype
can be changed trivially (so you can't depend on it).

> >>> That's very different than a range constraint, for instance, which is
> >>> outside the value, but it doesn't change the checking of the value.
That is,
> >>> values don't have constraints.
> >>
> >> The values are not same, String is not String (1..80).
> >
> > String is a type, not a value. String(1..80) is a subtype, not value.
"ABC"
> > is a value and that value includes its bounds.
>
> No, that depends on the type of "ABC". What is "ABC"'First? There is no
> logical way to derive it from the value otherwise than voluntarily set it
> at some arbitrary value, like 1.

No, I meant that a value is a set of components and bounds, "ABC" is
(almost) the closest thing that you can write. A literal is not a value,
either. There is no notation for a value! Every value has
bounds/discriminants; where they come from is part of the language
definition. Assuming them is just fine, or specifying them, or consulting an
oracle...

> > ...
> >> Hmm, what is the difference between elementary and non-elementary? In
which
> >> way mod 256 is more elementary than array (Positive range 1..8) of
Boolean?
> >
> > One is a single value, the other is a set of values. You can do math on
the
> > former to extract bits, but you can't get at them directly.
>
> Neither I can do it with the latter. There is an operation which extracts
> bits from the value. This operation has the parameter of some other type
> and the result of third. I could define such operation on the former or
> disallow it on the latter making the type private. Would that change its
> elementariness?

No, of course not. But we're not talking about user-defined operations,
we're talking about what is available by default.

> Just per view? Wouldn't F'Exponent make F non-elementary?

You're probably right; but of course Float types follow no sane model so I
don't care much about them. You can't design anything sensible if you worry
about them. Just bolt 'em on to whatever model you're using and continue.
;-)

> What about Boolean xor? May I claim that xor extracts a component of its
> first Boolean argument in some Platonic universe? It just makes no sense
to
> me.

You could argue anything, but doing so doesn't make it sensible.

> >> Because presently discriminants are not allowed, so, I presume, they
are
> >> all static. I.e. it definitely works! (:-))
> >
> > Discriminants are not allowed where? I was talking about where they are
> > allowed; if you extend them to be allowed everywhere.
>
> Yes, I meant that nothing would change for the types which presently have
> no discriminants, if we allowed but not used them.

OK. But your premise is not really true; the compiler complexity would jump
dramatically, and thus the number of bugs in the compiler would jump as
well. Similarly, the language definition would almost certainly be written
for types with discriminants; the rules for the no discriminant case would
no longer exist separately, and thus they would be subtly different.

> > Of course, a compiler
> > could special case no possible discriminants (I think it would have to,
> > adding a complexity). But if you allow adding them to extensions (and it
> > seems you should), then not 'Class ever is known to not have
discriminants.
>
> 'Class is a difficult case. And a general question regarding it is, should
> it be possible to have it "hyper-dispatching"? [sorry, for inventing new
> terms on the fly]? I mean T'Class'Class. If yes, then we will have
> different levels of tags. Another question is whether
> "multiple-polymorphic" things were allowed. Here I mean multiple of tags
at
> the same level: T'Class(1), T'Class(2) etc.
>
> I think these questions have to be answered in order to build a sane OO
> types system. What I do believe is that this system could be uniformly
> expressed in terms discriminants and impose no *any* penalty on computing
> with specific types.

Maybe. I'm not so sure. But in the absense of a real attempt to do so, who
can tell?

> > So they're almost always dynamic, and they have to almost always be part
of
> > the value. (And there are a lot more uses of 'Class in your universe
without
> > generics!)
>
> Yes, T'Class always has the tag (which is not necessarily dynamic).

The original object's tag might not be dynamic, and might be possible to be
omitted (even if it is logically present). But once you pass it to T'Class,
you have to include the tag dynamically, because it can be anything. (Well,
unless you are engaging in full-program optimization. But that's not
practical in real systems today; anything added on the fly destroys
full-program optimization.)

> >>>> The values of statically constrained / specific types will have no
> >>>> discriminants / tags. Dynamically constrained / polymorphic values
will
> >>>> have it, just as dynamically constrained strings have a dope. Only
the
> >>>> [by-reference] types with the reserved words tagged or limited will
have
> >>>> discriminants and the tag among them stored the value. I think it is
a
> >>>> doable program.
> >>>
> >>> Maybe, but only if you're successful in getting rid of generics
> >>
> >> If no new formal generic types will be introduced, then I don't see it
as a
> >> big deal. Possibly generics will never be get right, but that is not
> >> because of discriminants. (:-))
> >
> > If you do shared generics as we do, generics essentially double the work
for
> > everything. You idea would multiply it by 4 again. I think that's beyond
my
> > ability to imagine...
>
> It is not obvious to me. I guess that "type X is new Y with private" is
> where it should stop. Certainly, I don't want to try to express the types
> constraints in formal generic parameters. It would be a Sisyphean task
> worth of nothing.

Your scheme boils down to having a very general type system for which the
compiler recognizes and special cases any combination of things where it can
be done better (that is, discriminants can be omitted, tags can be omitted,
by-reference parameter passing should be turned to by-value, etc.) There
would be no syntaxtic "clues" as to when such optimizations could be done;
there could be nothing consistent about the representation of types. Very
little about how to build compilers as I know it could be used.

Perhaps, if you are starting with a completely blank page with really
brilliant people, it could be done more cheaply than I could. But then the
problems inherient in starting from scratch would occur: lots of bugs,
especially coming from places where the rules don't fit the design.

> > But I was referring to your previous
> > comments on how lousy generics are in a general way. I was presuming
that
> > your ideal language would not have them. But then you'd have to have a
lot
> > of operations on 'Class (to get a polymorphic Put, for one example). In
> > which case there would be far more dispatching calls than in Ada (we
tend to
> > use generics rather than inheritance, I think).
>
> Certainly, but I guess that shared generic bodies have to "dispatch" to
the
> actual "with procedure" as well. In the end it should turn equivalent,
> because, there is no implicit re-dispatch in Ada.

That's my point; it is farily equivalent. And there is essentially nothing
static in our generic bodies. I don't see how you could avoid that in a
"unified" language.

> If the class-wide bodies are inlined, then in comparable cases the tags
> will be known and all dispatching calls within them will be resolved
> statically. The rest would be space overhead for storing tags. Now, if the
> callee are inlined as well and type involved is not by-reference, then the
> compiler can remove call T -> T'Class -> T conversions, it would otherwise
> generate. That would mean no any overhead.

Very little can be practically inlined: either very short routines or
routines that are only called once (and the latter requires full-program
optimization, which is problematic as noted earlier). Anything else will
cause an explosion in code size. Thus, talking about what could happen when
something is inlined is irrelevant -- of course inlined code will be better
than non-inlined code, but the bulk of a program will not be inlined.

Similar, any *as if* optimizations are always fair game for a compiler, but
they're irrelevant when evaluating the semantics of the usual case. You
can't assume that optimizations are going happen - often they're only
applicable in trivial cases that rarely occur.

                           Randy.





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-23 19:18                               ` Dmitry A. Kazakov
@ 2007-04-24  0:15                                 ` Adam Beneschan
  2007-04-24 10:43                                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Adam Beneschan @ 2007-04-24  0:15 UTC (permalink / raw)


On Apr 23, 12:18 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> >>    type GUI_Boolean (Defined : Boolean := True) is (False, True);
>
> >> When Defined = False, the value is rendered as blank and the user is forced
> >> to enter it before it closes the dialog box.
>
> > X, Y : GUI_Boolean;
>
> > If you say X = Y, does it compare just the values, or does it compare
> > the discriminants also?
>
> That depends on how equality operation were defined for the given type. In
> the concrete case of GUI_Boolean, the user-defined "=" would raise
> Constraint_Error if at least one of the discriminants is false.

OK, I've got it.

   function "=" (X, Y : GUI_Boolean) return Boolean is
   begin
      if not X.Defined or else not Y.Defined then
         raise Constraint_Error;
      else
         return X = Y;
      end if;
    end "=";

Is that how you thought this user-defined "=" would be written?


> > What does "X = True" mean?  Does X.Defined have any effect on the
> > value of this expression?
>
> > OK, X is a GUI_Boolean that has Defined=false.  You now want to create
> > Y to be a GUI_Boolean that has the same value as X but Defined=true.
>
> This is semantically wrong for GUI_Boolean. An undefined value has no
> defined value...

I think you've missed the point.  If you want a feature like this in
the language, you can't base the whole semantics on one particular
example you happened to come up with (or that you happened to run
across a use for when you were working on some particular project).
The design of the feature in the language has to be more general than
that, and it has to include cases where a discriminant has some
meaning other than "This value is defined".



> > There are lots of syntactic and semantic issues involved with sticking
> > a discriminant on a scalar that you probably haven't thought through.
>
> All these problems were solved for the type String. In general, the
> problems you have referred equally apply to attributes of values. Ada has
> lots of attributes of values, whether scalar or not. That never was a
> problem.

But if you want the ability to put a discriminant on a scalar, the
meaning of the discriminant is *user*-defined, not language defined.
That isn't the case with any of the attributes on String.  Those
attributes are defined by the language.  I believe that the kinds of
discriminants you refer to pose a whole new set of problems that do
*not* apply to the String type.  For example, you need new syntax just
to allow the programmer to write the user-defined "=" functions that
you've referred to.  For another example, when you have an expression
of type String, the String attributes are defined by the language (at
least in most cases), so all the program has to do is give the values
of the character components; but since a discriminant's meaning is
user-defined, the language has to give the user a way to specify the
correct value; and as one of my examples hinted at, I don't think the
current language syntax is enough to handle this without some pretty
major surgery.

                                          -- Adam




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

* Re: Rational for not making cursor tagged in Containers
  2007-04-22  8:38                               ` Dmitry A. Kazakov
  2007-04-23 23:26                                 ` Randy Brukardt
@ 2007-04-24  8:58                                 ` Georg Bauhaus
  2007-04-24 12:21                                   ` Dmitry A. Kazakov
  1 sibling, 1 reply; 66+ messages in thread
From: Georg Bauhaus @ 2007-04-24  8:58 UTC (permalink / raw)


On Sun, 2007-04-22 at 10:38 +0200, Dmitry A. Kazakov wrote:

> 'Class is a difficult case. And a general question regarding it is, should
> it be possible to have it "hyper-dispatching"? [sorry, for inventing new
> terms on the fly]? I mean T'Class'Class.

I'm dense, is there any difference between T'Class and T'Class'Class?
When I assume Ada 95, and then
  T'Class ~ The tree of types rooted at T
  T'Class'Class ~ The tree of types rooted at T'Class
  ---
  T'Class'Class ~ The tree of types rooted at
                    the tree of types rooted at T

Isn't this the same set when it comes to actually performing
some operation?






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

* Re: Rational for not making cursor tagged in Containers
  2007-04-24  0:15                                 ` Adam Beneschan
@ 2007-04-24 10:43                                   ` Dmitry A. Kazakov
  2007-04-24 16:27                                     ` Adam Beneschan
  0 siblings, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-24 10:43 UTC (permalink / raw)


On 23 Apr 2007 17:15:06 -0700, Adam Beneschan wrote:

> On Apr 23, 12:18 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>>>>    type GUI_Boolean (Defined : Boolean := True) is (False, True);
>>
>>>> When Defined = False, the value is rendered as blank and the user is forced
>>>> to enter it before it closes the dialog box.
>>
>>> X, Y : GUI_Boolean;
>>
>>> If you say X = Y, does it compare just the values, or does it compare
>>> the discriminants also?
>>
>> That depends on how equality operation were defined for the given type. In
>> the concrete case of GUI_Boolean, the user-defined "=" would raise
>> Constraint_Error if at least one of the discriminants is false.
> 
> OK, I've got it.
> 
>    function "=" (X, Y : GUI_Boolean) return Boolean is
>    begin
>       if not X.Defined or else not Y.Defined then
>          raise Constraint_Error;
>       else
>          return X = Y;
>       end if;
>     end "=";
> 
> Is that how you thought this user-defined "=" would be written?

Yup, the predefined "=" should be renamed first.

>>> What does "X = True" mean?  Does X.Defined have any effect on the
>>> value of this expression?
>>
>>> OK, X is a GUI_Boolean that has Defined=false.  You now want to create
>>> Y to be a GUI_Boolean that has the same value as X but Defined=true.
>>
>> This is semantically wrong for GUI_Boolean. An undefined value has no
>> defined value...
> 
> I think you've missed the point.  If you want a feature like this in
> the language, you can't base the whole semantics on one particular
> example you happened to come up with (or that you happened to run
> across a use for when you were working on some particular project).
> The design of the feature in the language has to be more general than
> that, and it has to include cases where a discriminant has some
> meaning other than "This value is defined".

I don't see any problems with generation of a predefined "=" and literals
(True, False). [True is a literal of the type GUI_Boolean, with all
consequences of that.]

For unconstrained enumeration types (no default value for a discriminant),
literals should be generated abstract [primitive operations], to be
overridden if the type is not abstract.

>>> There are lots of syntactic and semantic issues involved with sticking
>>> a discriminant on a scalar that you probably haven't thought through.
>>
>> All these problems were solved for the type String. In general, the
>> problems you have referred equally apply to attributes of values. Ada has
>> lots of attributes of values, whether scalar or not. That never was a
>> problem.
> 
> But if you want the ability to put a discriminant on a scalar, the
> meaning of the discriminant is *user*-defined, not language defined.
> That isn't the case with any of the attributes on String. Those
> attributes are defined by the language.  I believe that the kinds of
> discriminants you refer to pose a whole new set of problems that do
> *not* apply to the String type.  For example, you need new syntax just
> to allow the programmer to write the user-defined "=" functions that
> you've referred to.  For another example, when you have an expression
> of type String, the String attributes are defined by the language (at
> least in most cases), so all the program has to do is give the values
> of the character components; but since a discriminant's meaning is
> user-defined, the language has to give the user a way to specify the
> correct value; and as one of my examples hinted at, I don't think the
> current language syntax is enough to handle this without some pretty
> major surgery.

I don't see any problem with that. The values of scalar types are
constructed using literals and operations defined on them. The predefined
equality (if any) involves the discriminant value.

If the user is unable to implement equality, then it is not because there
should be no discriminants. It is because the user has chosen a wrong type.
And it is an extremely useful language feature not to let him to compare
incomparable things.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-23 23:26                                 ` Randy Brukardt
@ 2007-04-24 10:43                                   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-24 10:43 UTC (permalink / raw)


On Mon, 23 Apr 2007 18:26:39 -0500, Randy Brukardt wrote:

> You said "Known discriminants are undeterminable from constrained values
> [for sanity reasons]." So where else do they come from? The type of the
> value contains no information (they're always unconstrained); the subtype
> can be changed trivially (so you can't depend on it).

I have to. The same problem exists with the strings, when a string object
is renamed to an object of a string subtype with different bounds. The
compiler silently ignores new bounds. This is *wrong* and it has to be
changed. The rule should be: a constraint once set on a subtype cannot be
changed without construction of a semantically new value.

>> No, that depends on the type of "ABC". What is "ABC"'First? There is no
>> logical way to derive it from the value otherwise than voluntarily set it
>> at some arbitrary value, like 1.
> 
> No, I meant that a value is a set of components and bounds, "ABC" is
> (almost) the closest thing that you can write. A literal is not a value,
> either. There is no notation for a value!

Yes, of course. Values do not exist in the program. You are right, I should
have used "object" instead of "value."

Still bounds is not necessary in the string value, which is an ordered set
of characters. You can enumerate that set in any way.

>>>> Hmm, what is the difference between elementary and non-elementary? In which
>>>> way mod 256 is more elementary than array (Positive range 1..8) of Boolean?
>>>
>>> One is a single value, the other is a set of values. You can do math on the
>>> former to extract bits, but you can't get at them directly.
>>
>> Neither I can do it with the latter. There is an operation which extracts
>> bits from the value. This operation has the parameter of some other type
>> and the result of third. I could define such operation on the former or
>> disallow it on the latter making the type private. Would that change its
>> elementariness?
> 
> No, of course not. But we're not talking about user-defined operations,
> we're talking about what is available by default.
> 
>> Just per view? Wouldn't F'Exponent make F non-elementary?
> 
> You're probably right; but of course Float types follow no sane model so I
> don't care much about them. You can't design anything sensible if you worry
> about them. Just bolt 'em on to whatever model you're using and continue.
> ;-)
> 
>> What about Boolean xor? May I claim that xor extracts a component of its
>> first Boolean argument in some Platonic universe? It just makes no sense to
>> me.
> 
> You could argue anything, but doing so doesn't make it sensible.

The point is that there is no way to define elementariness otherwise than
in terms of operations defined on the type. So in a language with ADTs,
where operations can be defined and disallowed, elementariness has no any
meaning other than, say, no function "." (X : T) return * is invisible in
the current context. Why should visibility of "." or "()" have any effect
on discriminants?

>>> Of course, a compiler
>>> could special case no possible discriminants (I think it would have to,
>>> adding a complexity). But if you allow adding them to extensions (and it
>>> seems you should), then not 'Class ever is known to not have discriminants.
>>
>> 'Class is a difficult case. And a general question regarding it is, should
>> it be possible to have it "hyper-dispatching"? [sorry, for inventing new
>> terms on the fly]? I mean T'Class'Class. If yes, then we will have
>> different levels of tags. Another question is whether
>> "multiple-polymorphic" things were allowed. Here I mean multiple of tags at
>> the same level: T'Class(1), T'Class(2) etc.
>>
>> I think these questions have to be answered in order to build a sane OO
>> types system. What I do believe is that this system could be uniformly
>> expressed in terms discriminants and impose no *any* penalty on computing
>> with specific types.
> 
> Maybe. I'm not so sure. But in the absense of a real attempt to do so, who
> can tell?

Somebody who would try it. (:-))

>>> So they're almost always dynamic, and they have to almost always be part of
>>> the value. (And there are a lot more uses of 'Class in your universe without
>>> generics!)
>>
>> Yes, T'Class always has the tag (which is not necessarily dynamic).
> 
> The original object's tag might not be dynamic, and might be possible to be
> omitted (even if it is logically present). But once you pass it to T'Class,
> you have to include the tag dynamically, because it can be anything.

Yes, this is the price to pay for sharing the bodies.

> (Well,
> unless you are engaging in full-program optimization. But that's not
> practical in real systems today; anything added on the fly destroys
> full-program optimization.)

Another possibility could be lazy expressions, so that class-wide value
will be constructed in the body later, probably never when the tag is used
solely for dispatch. But passing closures might be even more expensive.

> Your scheme boils down to having a very general type system for which the
> compiler recognizes and special cases any combination of things where it can
> be done better (that is, discriminants can be omitted, tags can be omitted,
> by-reference parameter passing should be turned to by-value, etc.) There
> would be no syntaxtic "clues" as to when such optimizations could be done;
> there could be nothing consistent about the representation of types. Very
> little about how to build compilers as I know it could be used.

Actually, I wished to add some "clues." Otherwise, I agree, it would not
work. It should not become another question of optimization. It should be
possible to explicitly state that the constrained subtypes of the given
type have no stored discriminants. Further there should be a way to tell
that all discriminant expressions of static arguments to be evaluated at
compile time.

In my view it is more serious problem that allowing discriminants
everywhere. Because I see no obvious way to convert a "Constraint_Exception
might be raised at run-time" into "this program is illegal."

> Perhaps, if you are starting with a completely blank page with really
> brilliant people, it could be done more cheaply than I could. But then the
> problems inherient in starting from scratch would occur: lots of bugs,
> especially coming from places where the rules don't fit the design.

I think that it would not be worth any efforts in that case. The goal
should be a much simpler language with much less classes of types and
special cases. What I want is that record, array and T'Class became
user-defined things.

> That's my point; it is farily equivalent. And there is essentially nothing
> static in our generic bodies. I don't see how you could avoid that in a
> "unified" language.

That is not the goal. For the start it would be good enough just to get rid
of generics...

Also the programming techniques and patterns customary used in class-wide
programming are quite different from ones used with generics. One cannot
foresee the effect of the shift. One should really try and see.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-24  8:58                                 ` Georg Bauhaus
@ 2007-04-24 12:21                                   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-24 12:21 UTC (permalink / raw)


On Tue, 24 Apr 2007 10:58:48 +0200, Georg Bauhaus wrote:

> On Sun, 2007-04-22 at 10:38 +0200, Dmitry A. Kazakov wrote:
> 
>> 'Class is a difficult case. And a general question regarding it is, should
>> it be possible to have it "hyper-dispatching"? [sorry, for inventing new
>> terms on the fly]? I mean T'Class'Class.
> 
> I'm dense, is there any difference between T'Class and T'Class'Class?

If you were allowed to derive from any type to get at the class of, then
you could do:

type Object is ...;
procedure Foo (X : Object'Class);
   -- Does not dispatch on Object'Class

type Meta_Object is new Object'Class with ...;
procedure Bar (X : Meta_Object);
   -- Dispatches on Meta_Object

I cannot think of any useful example for this. Perhaps:

type Node;
type Node_Ptr is access Node;

type Node is new Object'Class with record
   Previous : Node_Ptr;
   Next : Node_Ptr;
end record;

Which is essentially:

type Node (T : Tag) is record
   Previous : Node_Ptr;
   Next : Node_Ptr;
   Value : Object'Class (T);
end record;

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-24 10:43                                   ` Dmitry A. Kazakov
@ 2007-04-24 16:27                                     ` Adam Beneschan
  2007-04-24 20:19                                       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Adam Beneschan @ 2007-04-24 16:27 UTC (permalink / raw)


On Apr 24, 3:43 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> >>> X, Y : GUI_Boolean;
>
> >>> If you say X = Y, does it compare just the values, or does it compare
> >>> the discriminants also?
>
> >> That depends on how equality operation were defined for the given type. In
> >> the concrete case of GUI_Boolean, the user-defined "=" would raise
> >> Constraint_Error if at least one of the discriminants is false.
>
> > OK, I've got it.
>
> >    function "=" (X, Y : GUI_Boolean) return Boolean is
> >    begin
> >       if not X.Defined or else not Y.Defined then
> >          raise Constraint_Error;
> >       else
> >          return X = Y;
> >       end if;
> >     end "=";
>
> > Is that how you thought this user-defined "=" would be written?
>
> Yup, the predefined "=" should be renamed first.

So a user-defined  "=" that causes a stack overflow due to infinite
recursion doesn't bother you?

You still don't see the issue, do you?

> > I think you've missed the point.  If you want a feature like this in
> > the language, you can't base the whole semantics on one particular
> > example you happened to come up with (or that you happened to run
> > across a use for when you were working on some particular project).
> > The design of the feature in the language has to be more general than
> > that, and it has to include cases where a discriminant has some
> > meaning other than "This value is defined".
>
> I don't see any problems with generation of a predefined "=" and literals
> (True, False). [True is a literal of the type GUI_Boolean, with all
> consequences of that.]

If True has type GUI_Boolean, then it must have a "Defined"
discriminant.  What is True.Defined?  How does the programmer indicate
what it would be?  (And if you say that True.Defined is "true" because
"true" is a defined value, then you still don't get it---the Ada
language isn't going to know that, and you're going to need a way to
tell it that.)

> > and as one of my examples hinted at, I don't think the
> > current language syntax is enough to handle this without some pretty
> > major surgery.
>
> I don't see any problem with that.

Sure you don't, because you're not the one who'd have to do the
surgery.

                                    -- Adam




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

* Re: Rational for not making cursor tagged in Containers
  2007-04-24 16:27                                     ` Adam Beneschan
@ 2007-04-24 20:19                                       ` Dmitry A. Kazakov
  2007-04-26  0:58                                         ` Adam Beneschan
  0 siblings, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-24 20:19 UTC (permalink / raw)


On 24 Apr 2007 09:27:37 -0700, Adam Beneschan wrote:

> On Apr 24, 3:43 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>>>>> X, Y : GUI_Boolean;
>>
>>>>> If you say X = Y, does it compare just the values, or does it compare
>>>>> the discriminants also?
>>
>>>> That depends on how equality operation were defined for the given type. In
>>>> the concrete case of GUI_Boolean, the user-defined "=" would raise
>>>> Constraint_Error if at least one of the discriminants is false.
>>
>>> OK, I've got it.
>>
>>>    function "=" (X, Y : GUI_Boolean) return Boolean is
>>>    begin
>>>       if not X.Defined or else not Y.Defined then
>>>          raise Constraint_Error;
>>>       else
>>>          return X = Y;
>>>       end if;
>>>     end "=";
>>
>>> Is that how you thought this user-defined "=" would be written?
>>
>> Yup, the predefined "=" should be renamed first.
> 
> So a user-defined  "=" that causes a stack overflow due to infinite
> recursion doesn't bother you?

> You still don't see the issue, do you?

Which issue? As I said if you want to get at the predefined "=" you have to
rename it first:

type GUI_Boolean (Defined : Boolean := True) is (True, False);
function Equal (Left, Right : GUI_Boolean) return Boolean renames "=";
function "=" (Left, Right : GUI_Boolean) return Boolean;

function "=" (Left, Right : GUI_Boolean) return Boolean is
begin
   if not (X.Defined and then Y.Defined) then
      raise Constraint_Error;
   else
      return Equal (X, Y);
   end if;
end "=";

>> I don't see any problems with generation of a predefined "=" and literals
>> (True, False). [True is a literal of the type GUI_Boolean, with all
>> consequences of that.]
> 
> If True has type GUI_Boolean, then it must have a "Defined"
> discriminant.

It does (the GUI_Boolean returned by the literal has it).

> What is True.Defined?  How does the programmer indicate
> what it would be?  (And if you say that True.Defined is "true" because
> "true" is a defined value, then you still don't get it---the Ada
> language isn't going to know that, and you're going to need a way to
> tell it that.)

True is a literal. The rule is quite simple. If the literal is not abstract
and not overridden then its discriminants are defined by the corresponding
default expressions.

If absence of aggregates was your concern, that is not a problem either:

function Undefined return GUI_Boolean is
   Result : GUI_Boolean (False);
begin
   return Result;
end Undefined:

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-24 20:19                                       ` Dmitry A. Kazakov
@ 2007-04-26  0:58                                         ` Adam Beneschan
  2007-04-26  7:50                                           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Adam Beneschan @ 2007-04-26  0:58 UTC (permalink / raw)


On Apr 24, 1:19 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On 24 Apr 2007 09:27:37 -0700, Adam Beneschan wrote:
>
>
>
> > On Apr 24, 3:43 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> > wrote:
>
> >>>>> X, Y : GUI_Boolean;
>
> >>>>> If you say X = Y, does it compare just the values, or does it compare
> >>>>> the discriminants also?
>
> >>>> That depends on how equality operation were defined for the given type. In
> >>>> the concrete case of GUI_Boolean, the user-defined "=" would raise
> >>>> Constraint_Error if at least one of the discriminants is false.
>
> >>> OK, I've got it.
>
> >>>    function "=" (X, Y : GUI_Boolean) return Boolean is
> >>>    begin
> >>>       if not X.Defined or else not Y.Defined then
> >>>          raise Constraint_Error;
> >>>       else
> >>>          return X = Y;
> >>>       end if;
> >>>     end "=";
>
> >>> Is that how you thought this user-defined "=" would be written?
>
> >> Yup, the predefined "=" should be renamed first.
>
> > So a user-defined  "=" that causes a stack overflow due to infinite
> > recursion doesn't bother you?
> > You still don't see the issue, do you?
>
> Which issue? As I said if you want to get at the predefined "=" you have to
> rename it first:

OK, I didn't understand what you meant.  But that begs my original
question:

>>>>>> If you say X = Y, does it compare just the values, or does it compare
>>>>>> the discriminants also?

Your answer to that didn't really answer the question about predefined
equality, but went into some stuff about user-defined equality.  So
we're back where we started.  Does the predefined equality compare
just the values, or does it compare the discriminants also?

Now, it looks like you're saying it would compare just the values, in
order to make this user-defined equality work... well, now, you're
introducing an inconsistency.  The predefined equality on discriminant
record types compares the discriminants.  But predefined equality on
your discriminant scalar types doesn't.  Or else, if it does, that
will work in this particular case---but for more general uses of this
discriminant scalar thing, one may still need the ability to test the
values for equality, without also comparing the discriminants, in
order to *write* a user-defined "=" for the type---and you still
haven't provided a way to do that.


> >> I don't see any problems with generation of a predefined "=" and literals
> >> (True, False). [True is a literal of the type GUI_Boolean, with all
> >> consequences of that.]
>
> > If True has type GUI_Boolean, then it must have a "Defined"
> > discriminant.
>
> It does (the GUI_Boolean returned by the literal has it).
>
> > What is True.Defined?  How does the programmer indicate
> > what it would be?  (And if you say that True.Defined is "true" because
> > "true" is a defined value, then you still don't get it---the Ada
> > language isn't going to know that, and you're going to need a way to
> > tell it that.)
>
> True is a literal. The rule is quite simple. If the literal is not abstract
> and not overridden then its discriminants are defined by the corresponding
> default expressions.
>
> If absence of aggregates was your concern, that is not a problem either:
>
> function Undefined return GUI_Boolean is
>    Result : GUI_Boolean (False);
> begin
>    return Result;
> end Undefined:

Hmmm...  OK, I see how that might work in that particular case.
However, that does make it seem that, although your idea about putting
discriminants on enumeration literals seems like a nice general idea,
it won't work unless there is only one possible value for the
discriminant for which the enumeration value makes any sense.  That's
the case for your GUI_Boolean example---if Defined=True, the
enumeration part of the value can be used, and if Defined=False, the
enumeration part is meaningless.  That's not very general, though.
Suppose, for example, you wanted a GUI_Boolean with three states:
Not_Defined, Defined_By_Config, Defined_By_User, where the latter two
states would distinguish whether a Boolean value were set by some
default present in a configuration file (or the Winodws registry,
say), or were explicitly entered by the user.  Now you can't really do
this, without adding extra syntax and semantics to the language:

   type GUI_State is (Not_Defined, Defined_By_Config,
Defined_By_User);
   type GUI_Boolean (State : GUI_State := ???) is (False, True);

Whichever value you pick for the default State---Defined_By_Config or
Defined_By_User---you don't have a way to set up a GUI_Boolean whose
state is the other one and whose value is one of the False/True
literals.

I'm not going to spend any more time on this thread---I've spent too
much already.  But I'm convinced that (1) nobody will want to add this
feature to the language if the only possible use would be a "Defined"
setup like in your example, and (2) the work required to add extra
syntax, semantics, etc., to make this a more general feature would not
be worthwhile, when discriminant records can so easily be used to
accomplish the same thing and in a way that's easily understandable.

                                    -- Adam






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

* Re: Rational for not making cursor tagged in Containers
  2007-04-26  0:58                                         ` Adam Beneschan
@ 2007-04-26  7:50                                           ` Dmitry A. Kazakov
  2007-04-26  8:09                                             ` Markus E Leypold
  2007-04-26  8:33                                             ` Markus E Leypold
  0 siblings, 2 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-26  7:50 UTC (permalink / raw)


On 25 Apr 2007 17:58:12 -0700, Adam Beneschan wrote:

> On Apr 24, 1:19 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> On 24 Apr 2007 09:27:37 -0700, Adam Beneschan wrote:
>>
> Your answer to that didn't really answer the question about predefined
> equality, but went into some stuff about user-defined equality.  So
> we're back where we started.  Does the predefined equality compare
> just the values, or does it compare the discriminants also?

The predefined equality compares memory bit patterns. Observe, that for any
fundamental built-in type there is no way to define equality otherwise than
this way. An implementation shall ensure that different values of the
discriminants and the positions of values render predefined comparison to
false.

> Hmmm...  OK, I see how that might work in that particular case.
> However, that does make it seem that, although your idea about putting
> discriminants on enumeration literals seems like a nice general idea,
> it won't work unless there is only one possible value for the
> discriminant for which the enumeration value makes any sense.  That's
> the case for your GUI_Boolean example---if Defined=True, the
> enumeration part of the value can be used, and if Defined=False, the
> enumeration part is meaningless.  That's not very general, though.
> Suppose, for example, you wanted a GUI_Boolean with three states:
> Not_Defined, Defined_By_Config, Defined_By_User, where the latter two
> states would distinguish whether a Boolean value were set by some
> default present in a configuration file (or the Winodws registry,
> say), or were explicitly entered by the user.  Now you can't really do
> this, without adding extra syntax and semantics to the language:
> 
>    type GUI_State is (Not_Defined, Defined_By_Config,
> Defined_By_User);
>    type GUI_Boolean (State : GUI_State := ???) is (False, True);
> 
> Whichever value you pick for the default State---Defined_By_Config or
> Defined_By_User---you don't have a way to set up a GUI_Boolean whose
> state is the other one and whose value is one of the False/True
> literals.

Yes, and this is a desired feature. It is important to clearly understand
that discriminant is not yet-another-record-field. Discriminant is a
constraint put on the values. If you have two values of the type and three
values of the constraint, then it shouldn't wonder you that this construct
wouldn't be much usable. What is the difference between Defined_By_Config
True and Defined_By_User True? Just bad design and language misuse.

---------------
My point was, logically and semantically any type may have discriminants =
be dynamically constrained.

It is quite difficult (IMO impossible) to show why some special classes of
types may not be constrained. There exist very strong cases for real,
access and array types which indeed require discriminants. I mentioned them
in other posts. The rest is basically enumeration types and Robert Duff
asked for an example for Boolean type. It was a challenge to think an
example out, I hope you enjoyed it. For a more elaborated enumeration type
I would probably propose dynamically constrained ranges of, or something
similar. But again, that was not the point.

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-26  7:50                                           ` Dmitry A. Kazakov
@ 2007-04-26  8:09                                             ` Markus E Leypold
  2007-04-27  8:46                                               ` Dmitry A. Kazakov
  2007-04-27 20:44                                               ` Robert A Duff
  2007-04-26  8:33                                             ` Markus E Leypold
  1 sibling, 2 replies; 66+ messages in thread
From: Markus E Leypold @ 2007-04-26  8:09 UTC (permalink / raw)



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

> The predefined equality compares memory bit patterns. 

Without looking into the ARM -- I'd be surprised if the ARM defined it
like this. I'm sure it's more like

  - values numeric types shall be equal if their value are equal
  - array sahll be equal if they are of equal lengths and all components are equal
  - records are equal if all components are equal

Discriminants will complicate this a bit, but the fundamental idea
will stay the same. 

It's up to the implementation to stick to how it -- well -- implements
this semantics. If it compares bit patterns, it will have to pay
attention to uninitialized padding space, but on the other side
comparing bit patterns will probably be very fast. But it _could_ also
just generate loops of sequences of comparisons of the basic
components. As I said: I'm voncinced that's up to the implementation
and I'd suprised if "predefined equality compares memory bit patterns"
as per definition in the ARM.

> Observe, that for any fundamental built-in type there is no way to
> define equality otherwise than this way. An implementation shall
> ensure that different values of the discriminants and the positions
> of values render predefined comparison to false.

Regards -- Markus



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-26  7:50                                           ` Dmitry A. Kazakov
  2007-04-26  8:09                                             ` Markus E Leypold
@ 2007-04-26  8:33                                             ` Markus E Leypold
  2007-04-26 11:09                                               ` Markus E Leypold
  1 sibling, 1 reply; 66+ messages in thread
From: Markus E Leypold @ 2007-04-26  8:33 UTC (permalink / raw)



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

> On 25 Apr 2007 17:58:12 -0700, Adam Beneschan wrote:
>
>> On Apr 24, 1:19 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>> wrote:
>>> On 24 Apr 2007 09:27:37 -0700, Adam Beneschan wrote:
>>>
>> Your answer to that didn't really answer the question about predefined
>> equality, but went into some stuff about user-defined equality.  So
>> we're back where we started.  Does the predefined equality compare
>> just the values, or does it compare the discriminants also?
>
> The predefined equality compares memory bit patterns. Observe, that for any

Does it for tagged types? 

Regards -- Markus




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

* Re: Rational for not making cursor tagged in Containers
  2007-04-26  8:33                                             ` Markus E Leypold
@ 2007-04-26 11:09                                               ` Markus E Leypold
  0 siblings, 0 replies; 66+ messages in thread
From: Markus E Leypold @ 2007-04-26 11:09 UTC (permalink / raw)



Markus E Leypold <development-2006-8ecbb5cc8aREMOVETHIS@ANDTHATm-e-leypold.de> writes:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> On 25 Apr 2007 17:58:12 -0700, Adam Beneschan wrote:
>>
>>> On Apr 24, 1:19 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>>> wrote:
>>>> On 24 Apr 2007 09:27:37 -0700, Adam Beneschan wrote:
>>>>
>>> Your answer to that didn't really answer the question about predefined
>>> equality, but went into some stuff about user-defined equality.  So
>>> we're back where we started.  Does the predefined equality compare
>>> just the values, or does it compare the discriminants also?
>>
>> The predefined equality compares memory bit patterns. Observe, that for any
>
> Does it for tagged types? 

Forget this. I'm not sure what I wanted to say here :-).

Regards -- Markus





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

* Re: Rational for not making cursor tagged in Containers
  2007-04-26  8:09                                             ` Markus E Leypold
@ 2007-04-27  8:46                                               ` Dmitry A. Kazakov
  2007-04-27 11:37                                                 ` Markus E Leypold
  2007-04-27 20:44                                               ` Robert A Duff
  1 sibling, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-27  8:46 UTC (permalink / raw)


On Thu, 26 Apr 2007 10:09:20 +0200, Markus E Leypold wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> The predefined equality compares memory bit patterns. 
> 
> Without looking into the ARM -- I'd be surprised if the ARM defined it
> like this. I'm sure it's more like
> 
>   - values numeric types shall be equal if their value are equal

Exactly, values shall be equal if they are  ... equal! (:-))

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-27  8:46                                               ` Dmitry A. Kazakov
@ 2007-04-27 11:37                                                 ` Markus E Leypold
  2007-04-28 17:35                                                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Markus E Leypold @ 2007-04-27 11:37 UTC (permalink / raw)



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

> On Thu, 26 Apr 2007 10:09:20 +0200, Markus E Leypold wrote:
>
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> 
>>> The predefined equality compares memory bit patterns. 
>> 
>> Without looking into the ARM -- I'd be surprised if the ARM defined it
>> like this. I'm sure it's more like
>> 
>>   - values numeric types shall be equal if their value are equal
>
> Exactly, values shall be equal if they are  ... equal! (:-))

Well, surpise: That was not formulated well, but there is probably no
resonable way to define equality of primitive values (i.e. those not
composed from other values) in a programming language
specification. We just have to assume that anybody knows when two
values are equal.

But for all your scorn, I note you're (again) ditching the issue I
triee to address: That the ARM is not defining equality by comparing
memory patterns.

But -- would I have expected anything else?

Regards -- Markus



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-26  8:09                                             ` Markus E Leypold
  2007-04-27  8:46                                               ` Dmitry A. Kazakov
@ 2007-04-27 20:44                                               ` Robert A Duff
  1 sibling, 0 replies; 66+ messages in thread
From: Robert A Duff @ 2007-04-27 20:44 UTC (permalink / raw)


Markus E Leypold
<development-2006-8ecbb5cc8aREMOVETHIS@ANDTHATm-e-leypold.de> writes:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> The predefined equality compares memory bit patterns. 
>
> Without looking into the ARM -- I'd be surprised if the ARM defined it
> like this. I'm sure it's more like
>
>   - values numeric types shall be equal if their value are equal
>   - array sahll be equal if they are of equal lengths and all components are equal
>   - records are equal if all components are equal

That's correct.

There are cases where it can't compare bit patterns.

For floating point, negative zero is equal to positive zero.

For a boolean type with convention Fortran:

    type Logical is new Boolean;
    pragma Convention(Fortran, Logical);

The representation is "zero is false, anything else is true".

User-defined "=" composes properly in the tagged case.

- Bob



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-27 11:37                                                 ` Markus E Leypold
@ 2007-04-28 17:35                                                   ` Dmitry A. Kazakov
  2007-04-29  2:31                                                     ` Randy Brukardt
  0 siblings, 1 reply; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-28 17:35 UTC (permalink / raw)


On Fri, 27 Apr 2007 13:37:34 +0200, Markus E Leypold wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On Thu, 26 Apr 2007 10:09:20 +0200, Markus E Leypold wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>> 
>>>> The predefined equality compares memory bit patterns. 

You skipped the rest of my post, which says that equality is defined in the
terms of the positions and the discriminants.

>>> Without looking into the ARM -- I'd be surprised if the ARM defined it
>>> like this. I'm sure it's more like
>>> 
>>>   - values numeric types shall be equal if their value are equal
>>
>> Exactly, values shall be equal if they are  ... equal! (:-))
> 
> Well, surpise: That was not formulated well, but there is probably no
> resonable way to define equality of primitive values (i.e. those not
> composed from other values) in a programming language
> specification.

What is your point then? What do you disagree with?

> We just have to assume that anybody knows when two
> values are equal.

And this is supposed to be the definition of?

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



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

* Re: Rational for not making cursor tagged in Containers
  2007-04-28 17:35                                                   ` Dmitry A. Kazakov
@ 2007-04-29  2:31                                                     ` Randy Brukardt
  2007-04-29  8:45                                                       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 66+ messages in thread
From: Randy Brukardt @ 2007-04-29  2:31 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:zp8f8yxaqal5.xmxbdrzopa73$.dlg@40tude.net...
> On Fri, 27 Apr 2007 13:37:34 +0200, Markus E Leypold wrote:
...
> > We just have to assume that anybody knows when two
> > values are equal.
>
> And this is supposed to be the definition of?

It's not quite that bad, but it is close; see 4.5.2(10):

"For discrete types, the predefined relational operators are defined in
terms of corresponding mathematical operations on the position numbers of
the values of the operations."

It surely has nothing to do with bit patterns, but rather the mathematical
meaning of those bit patterns. The RM hands off "mathematical meaning" to
another reference.

In any case, Dmitry seems to be using his own terminology again; that can be
a issue when others of us are using the terminology defined in the RM.
Without a common terminology, it's very hard to have a reasonable discourse.
Even if we're talking about an Ada-like language rather than Ada itself, it
helps to stick to the terminology of the RM.

"Value" is one of the concepts that the RM does not try to define (which
doesn't help this discussion), although it uses the term a lot. In such a
case, it is supposed to have the conventional meaning associated with the
term in English - so I don't think it is possible to completely settle
this... ;-)

                                   Randy.






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

* Re: Rational for not making cursor tagged in Containers
  2007-04-29  2:31                                                     ` Randy Brukardt
@ 2007-04-29  8:45                                                       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 66+ messages in thread
From: Dmitry A. Kazakov @ 2007-04-29  8:45 UTC (permalink / raw)


On Sat, 28 Apr 2007 21:31:41 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:zp8f8yxaqal5.xmxbdrzopa73$.dlg@40tude.net...
>> On Fri, 27 Apr 2007 13:37:34 +0200, Markus E Leypold wrote:
> ...
>>> We just have to assume that anybody knows when two
>>> values are equal.
>>
>> And this is supposed to be the definition of?
> 
> It's not quite that bad, but it is close; see 4.5.2(10):
> 
> "For discrete types, the predefined relational operators are defined in
> terms of corresponding mathematical operations on the position numbers of
> the values of the operations."

I.e. they are defined in terms of positions, not values, which works no
longer we have these positions.

> It surely has nothing to do with bit patterns, but rather the mathematical
> meaning of those bit patterns.

Sure, but we cannot compare meanings on a computer, we can bit patterns
representing meanings. Assuming that different patterns correspond to
different meanings (=injective mapping of), we could compare patterns as if
they were meanings.

> "Value" is one of the concepts that the RM does not try to define (which
> doesn't help this discussion), although it uses the term a lot.

We should not blame RM for that. I guess value is just a narrower word for
meaning. So it just cannot be defined.

> In such a
> case, it is supposed to have the conventional meaning associated with the
> term in English - so I don't think it is possible to completely settle
> this... ;-)

Ah, but what about making cursors tagged? (:-))

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



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

end of thread, other threads:[~2007-04-29  8:45 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-04-19 16:05 Rational for not making cursor tagged in Containers Anh Vo
2007-04-19 18:25 ` Robert A Duff
2007-04-19 19:28   ` Anh Vo
2007-04-19 20:45     ` Robert A Duff
2007-04-19 21:43       ` Dmitry A. Kazakov
2007-04-19 23:59         ` Ray Blaak
2007-04-20  7:54           ` Dmitry A. Kazakov
2007-04-20 10:56             ` Georg Bauhaus
2007-04-20 10:39               ` Dmitry A. Kazakov
2007-04-20 14:42                 ` Georg Bauhaus
2007-04-20 14:45                   ` Georg Bauhaus
2007-04-20 15:13                   ` Dmitry A. Kazakov
2007-04-20 19:37                     ` Georg Bauhaus
2007-04-20 19:32                       ` Dmitry A. Kazakov
2007-04-20 20:59                         ` Robert A Duff
2007-04-20 22:14                           ` Dmitry A. Kazakov
2007-04-23 17:38                             ` Adam Beneschan
2007-04-23 19:18                               ` Dmitry A. Kazakov
2007-04-24  0:15                                 ` Adam Beneschan
2007-04-24 10:43                                   ` Dmitry A. Kazakov
2007-04-24 16:27                                     ` Adam Beneschan
2007-04-24 20:19                                       ` Dmitry A. Kazakov
2007-04-26  0:58                                         ` Adam Beneschan
2007-04-26  7:50                                           ` Dmitry A. Kazakov
2007-04-26  8:09                                             ` Markus E Leypold
2007-04-27  8:46                                               ` Dmitry A. Kazakov
2007-04-27 11:37                                                 ` Markus E Leypold
2007-04-28 17:35                                                   ` Dmitry A. Kazakov
2007-04-29  2:31                                                     ` Randy Brukardt
2007-04-29  8:45                                                       ` Dmitry A. Kazakov
2007-04-27 20:44                                               ` Robert A Duff
2007-04-26  8:33                                             ` Markus E Leypold
2007-04-26 11:09                                               ` Markus E Leypold
2007-04-20 19:55                       ` Randy Brukardt
2007-04-22  9:54                         ` Georg Bauhaus
2007-04-22 11:19                           ` Dmitry A. Kazakov
2007-04-20 20:44                       ` Robert A Duff
2007-04-21  5:38                         ` Randy Brukardt
2007-04-22  1:14                           ` Robert A Duff
2007-04-22  4:08                             ` Randy Brukardt
2007-04-20 20:11                     ` Randy Brukardt
2007-04-20 21:28                       ` Dmitry A. Kazakov
2007-04-21  5:33                         ` Randy Brukardt
2007-04-21  9:39                           ` Dmitry A. Kazakov
2007-04-22  4:28                             ` Randy Brukardt
2007-04-22  8:38                               ` Dmitry A. Kazakov
2007-04-23 23:26                                 ` Randy Brukardt
2007-04-24 10:43                                   ` Dmitry A. Kazakov
2007-04-24  8:58                                 ` Georg Bauhaus
2007-04-24 12:21                                   ` Dmitry A. Kazakov
2007-04-21  4:48                       ` unifying arrays and records (was Re: Rational for not making cursor tagged in Containers) Ray Blaak
2007-04-20 17:05             ` Rational for not making cursor tagged in Containers Ray Blaak
2007-04-20 18:46               ` Dmitry A. Kazakov
2007-04-20 18:52                 ` Ray Blaak
2007-04-20 19:54                   ` Robert A Duff
2007-04-20  1:18         ` Anh Vo
2007-04-20  7:53           ` Dmitry A. Kazakov
2007-04-20  9:26             ` Maciej Sobczak
2007-04-20 10:15               ` Dmitry A. Kazakov
2007-04-20 11:59           ` Jean-Pierre Rosen
2007-04-20 13:23             ` Anh Vo
2007-04-20 16:02               ` Jean-Pierre Rosen
2007-04-21  2:53                 ` Anh Vo
2007-04-20  3:03   ` Randy Brukardt
2007-04-20  2:53 ` Randy Brukardt
2007-04-20 16:08   ` Anh Vo

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