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