comp.lang.ada
 help / color / mirror / Atom feed
* container cursor type cannot be tagged
@ 2014-08-28 19:21 Stephen Leake
  2014-08-28 20:25 ` Randy Brukardt
  0 siblings, 1 reply; 9+ messages in thread
From: Stephen Leake @ 2014-08-28 19:21 UTC (permalink / raw)


In trying to build my own container package, I ran into a problem; the
Cursor type cannot be tagged. Which means we can't use "Cursor.op"
notation, which I've grown to really like.

The reason it can't be tagged is these two functions defined by
Ada.Iterator_Interfaces (and similar ones for reverse iteration):

   overriding function First (Object : Iterator) return Cursor;
   overriding function Next
     (Object   : Iterator;
      Position : Cursor)
     return Cursor;

Iterator is a tagged type, so Cursor can't be; Ada 2012 doesn't support
dispatching on multiple tagged types (LRM 3.9.3 12).

One solution to this is to define a new aspect Controlling_Type:

   overriding function First (Object : Iterator) return Cursor
   with Controlling_Type => Iterator;

which says to not use Cursor to dispatch calls to this subprogram. That
would be useful in other similar situations. I didn't find an AI on this
issue; would this be worth a proposal?

Another solution would be to provide another version of
Ada.Iterator_Interfaces, where Cursor is explicitly tagged, and these
functions use Cursor'Class. That seems more of a kludge.

-- 
-- Stephe


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

* Re: container cursor type cannot be tagged
  2014-08-28 19:21 container cursor type cannot be tagged Stephen Leake
@ 2014-08-28 20:25 ` Randy Brukardt
  2014-08-29  7:28   ` Dmitry A. Kazakov
  2014-08-29 14:50   ` Stephen Leake
  0 siblings, 2 replies; 9+ messages in thread
From: Randy Brukardt @ 2014-08-28 20:25 UTC (permalink / raw)


"Stephen Leake" <stephen_leake@stephe-leake.org> wrote in message 
news:85ppfkxvwg.fsf@stephe-leake.org...
> In trying to build my own container package, I ran into a problem; the
> Cursor type cannot be tagged. Which means we can't use "Cursor.op"
> notation, which I've grown to really like.

We of course noticed that when we originally designed the containers --  
operations that only take cursors cannot be called in prefix notation. 
Originally, neither the container nor the cursor was tagged for this reason, 
but eventually we decided it was silly to make it impossible to use prefix 
notation at all just because it can't always be used.

There doesn't seem to be a good solution that would allow the cursor to be 
tagged. But even untagged, you can't sensible extend the container because 
you really need to derive both the container and the cursor together. I 
tried to come up with a solution that would make both the container and 
cursor tagged, and would derive them in lock-step, but that gets to be a 
problem if the inherited routines are also primitive on other types.

Full multiple dispatch would of course work, but we've talked about that 
enough here. (Thanks Dmitry! :-)

...
> One solution to this is to define a new aspect Controlling_Type:
>
>   overriding function First (Object : Iterator) return Cursor
>   with Controlling_Type => Iterator;
>
> which says to not use Cursor to dispatch calls to this subprogram. That
> would be useful in other similar situations. I didn't find an AI on this
> issue; would this be worth a proposal?

Well, that's up to you. I'd think it's pretty weird; if one really wants a 
non-dispatching parameter, it should be declared as class-wide. 
Non-dispatching, non-class-wide tagged parameters almost always represent a 
bug in a program (we had a bunch in Claw, which tended to crash programs 
that derived things like fonts [tag check failures]; eventually we 
eliminated almost all of them). That's not so clear-cut for returns, but it 
seems weird to have a feature that only works for returns.

> Another solution would be to provide another version of
> Ada.Iterator_Interfaces, where Cursor is explicitly tagged, and these
> functions use Cursor'Class. That seems more of a kludge.

That seems to make more sense, honestly. But how are you dealing with the 
"can't have two tagged types" problem for the container itself? If it's 
untagged, you have the same problem about not allowing prefix notation, just 
in reverse (OK for cursors, bad for containers). If it's tagged, then the 
cursor can't be tagged. So I don't see much point in solving it at the 
iterator level if you can't solve it for the container itself (much more 
important).

If it was me, I'd put a container parameter on every operation (which would 
be the prefix), and cursors would work soley like array indexes. (This is 
much better if you're writing preconditions and especially global 
declarations, since you can then refer directly to the container rather than 
having it implicit. The Ada.Containers design is sub-optimal for 
correctness, unfortunately.) In such a case, you wouldn't need a cursor to 
be tagged.

You'd still want some sort of co-extension, however, (so a container 
extension would get a new cursor type) which Ada doesn't support.

                                        Randy.




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

* Re: container cursor type cannot be tagged
  2014-08-28 20:25 ` Randy Brukardt
@ 2014-08-29  7:28   ` Dmitry A. Kazakov
  2014-08-29  7:59     ` J-P. Rosen
  2014-08-29 23:08     ` Randy Brukardt
  2014-08-29 14:50   ` Stephen Leake
  1 sibling, 2 replies; 9+ messages in thread
From: Dmitry A. Kazakov @ 2014-08-29  7:28 UTC (permalink / raw)


On Thu, 28 Aug 2014 15:25:59 -0500, Randy Brukardt wrote:

> If it was me, I'd put a container parameter on every operation (which would 
> be the prefix), and cursors would work soley like array indexes.

Huh, remember our discussion about cursor/iterator being a bad idea?

That is another of multiple reasons why. Cursor tend to become a full class
with descendants and primitive operations which ends up in multiple
dispatch, for whatever reason not available. An index almost always can be
a "final" type which makes everything a lot easier.

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


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

* Re: container cursor type cannot be tagged
  2014-08-29  7:28   ` Dmitry A. Kazakov
@ 2014-08-29  7:59     ` J-P. Rosen
  2014-08-29  8:46       ` Dmitry A. Kazakov
  2014-08-29 23:08     ` Randy Brukardt
  1 sibling, 1 reply; 9+ messages in thread
From: J-P. Rosen @ 2014-08-29  7:59 UTC (permalink / raw)


Le 29/08/2014 09:28, Dmitry A. Kazakov a écrit :
> That is another of multiple reasons why. Cursor tend to become a full class
> with descendants and primitive operations which ends up in multiple
> dispatch, for whatever reason not available. An index almost always can be
> a "final" type which makes everything a lot easier.

Could you elaborate on what (in your view) is the difference between a
cursor and an index?

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


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

* Re: container cursor type cannot be tagged
  2014-08-29  7:59     ` J-P. Rosen
@ 2014-08-29  8:46       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 9+ messages in thread
From: Dmitry A. Kazakov @ 2014-08-29  8:46 UTC (permalink / raw)


On Fri, 29 Aug 2014 09:59:03 +0200, J-P. Rosen wrote:

> Le 29/08/2014 09:28, Dmitry A. Kazakov a écrit :
>> That is another of multiple reasons why. Cursor tend to become a full class
>> with descendants and primitive operations which ends up in multiple
>> dispatch, for whatever reason not available. An index almost always can be
>> a "final" type which makes everything a lot easier.
> 
> Could you elaborate on what (in your view) is the difference between a
> cursor and an index?

Unlike index cursor/iterator carries the object's identity. It alone is
sufficient to access the element. This logically decouples it (and the
element as well) from the container. Any link to the container gets hidden.
The identity is assumed invariant to container updates, which is only a
felt invariant, since it cannot be statically enforced. All this has far
reaching consequences for the usage, design and implementation.

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


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

* Re: container cursor type cannot be tagged
  2014-08-28 20:25 ` Randy Brukardt
  2014-08-29  7:28   ` Dmitry A. Kazakov
@ 2014-08-29 14:50   ` Stephen Leake
  2014-08-29 23:00     ` Randy Brukardt
  1 sibling, 1 reply; 9+ messages in thread
From: Stephen Leake @ 2014-08-29 14:50 UTC (permalink / raw)


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

>> One solution to this is to define a new aspect Controlling_Type:
>>
>>   overriding function First (Object : Iterator) return Cursor
>>   with Controlling_Type => Iterator;
>>
>> which says to not use Cursor to dispatch calls to this subprogram. That
>> would be useful in other similar situations. I didn't find an AI on this
>> issue; would this be worth a proposal?
>
> Well, that's up to you. I'd think it's pretty weird; if one really wants a 
> non-dispatching parameter, it should be declared as class-wide. 

Ok; at least you didn't say "we looked at that and it won't work because ...".

>> Another solution would be to provide another version of
>> Ada.Iterator_Interfaces, where Cursor is explicitly tagged, and these
>> functions use Cursor'Class. That seems more of a kludge.
>
> That seems to make more sense, honestly. But how are you dealing with the 
> "can't have two tagged types" problem for the container itself? 

I don't see the problem; I declared my container with tagged container
and cursor, and only had a problem when I tried to instantiate
Ada.Iterator_Interfaces. 

On the other hand, I hope that the Controlling_Type aspect could be used
to resolve any problems due to multiple tagged types.

I agree that deriving from the container and cursor together is not a
solved problem. This arises from the confusion of "derivable" and "can
use object.method" features; both depend on the type being tagged. In my
case, I don't care about further derivation, but I do care about
object.method. So my solution is just to say "this container design is
not intended to support derived containers". Perhaps we need to borrow
"final" from C++11/Java?

-- 
-- Stephe


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

* Re: container cursor type cannot be tagged
  2014-08-29 14:50   ` Stephen Leake
@ 2014-08-29 23:00     ` Randy Brukardt
  2014-08-30 15:16       ` Stephen Leake
  0 siblings, 1 reply; 9+ messages in thread
From: Randy Brukardt @ 2014-08-29 23:00 UTC (permalink / raw)


"Stephen Leake" <stephen_leake@stephe-leake.org> wrote in message 
news:85d2bjxscf.fsf@stephe-leake.org...
> "Randy Brukardt" <randy@rrsoftware.com> writes:
>> That seems to make more sense, honestly. But how are you dealing with the
>> "can't have two tagged types" problem for the container itself?
>
> I don't see the problem; I declared my container with tagged container
> and cursor, and only had a problem when I tried to instantiate
> Ada.Iterator_Interfaces.

How did you do that? Any operation that takes a container and a cursor is 
illegal if both are tagged. I don't see how you could have a constructor for 
a cursor in that case (it must at least take a container and return a 
cursor), and operations involving container updates could work as 
cursor-only operations but are dangerous (because they would allow writing 
constant containers).

Using Cursor'Class in this circumstance is a lie (there never will be any 
derived types that work) and of course forces checking to runtime (or not at 
all).

                                  Randy.




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

* Re: container cursor type cannot be tagged
  2014-08-29  7:28   ` Dmitry A. Kazakov
  2014-08-29  7:59     ` J-P. Rosen
@ 2014-08-29 23:08     ` Randy Brukardt
  1 sibling, 0 replies; 9+ messages in thread
From: Randy Brukardt @ 2014-08-29 23:08 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:c8utnmednhss.tg5692sifke0$.dlg@40tude.net...
> On Thu, 28 Aug 2014 15:25:59 -0500, Randy Brukardt wrote:
>
>> If it was me, I'd put a container parameter on every operation (which 
>> would
>> be the prefix), and cursors would work soley like array indexes.
>
> Huh, remember our discussion about cursor/iterator being a bad idea?

No sorry, I don't. But I do know that I was against that model of cursors 
from the beginning; I just wasn't able to explain why well enough to 
convince anyone else.

> That is another of multiple reasons why. Cursor tend to become a full 
> class
> with descendants and primitive operations which ends up in multiple
> dispatch, for whatever reason not available. An index almost always can be
> a "final" type which makes everything a lot easier.

But please note that iterators are a very different case. They necessarily 
encapsulate some state and that state is intimately tied to the container --  
it doesn't make sense to separate them.

Also note that a cursor would always need to include some indication of the 
container it belongs to, in order that the library can prevent using the 
cursor with the wrong container. Since these are almost always going to be 
implemented as wrapped access types, using one with the wrong container 
would lead to havoc. (And one of the most important properties of the Ada 
containers is that they never cause more havoc than a bare, fully checked 
array could.)

The problem comes from using the cursor separately from the container, not 
so much from the fact that cursors know their containers. (The indication 
does not need to be a pointer in this model, a serial number would be 
enough, so just because there is an indication doesn't mean that one could 
use the cursor without the container.)

                                                        Randy.



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

* Re: container cursor type cannot be tagged
  2014-08-29 23:00     ` Randy Brukardt
@ 2014-08-30 15:16       ` Stephen Leake
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Leake @ 2014-08-30 15:16 UTC (permalink / raw)


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

> "Stephen Leake" <stephen_leake@stephe-leake.org> wrote in message 
> news:85d2bjxscf.fsf@stephe-leake.org...
>> "Randy Brukardt" <randy@rrsoftware.com> writes:
>>> That seems to make more sense, honestly. But how are you dealing with the
>>> "can't have two tagged types" problem for the container itself?
>>
>> I don't see the problem; I declared my container with tagged container
>> and cursor, and only had a problem when I tried to instantiate
>> Ada.Iterator_Interfaces.
>
> How did you do that? Any operation that takes a container and a cursor is 
> illegal if both are tagged. I don't see how you could have a constructor for 
> a cursor in that case (it must at least take a container and return a 
> cursor), 

It returns Cursor'class.  

> Using Cursor'Class in this circumstance is a lie (there never will be any 
> derived types that work) 

Right. But I don't care about derived types; Container and Cursor are
tagged _only_ to allow using Object.Method.

> and of course forces checking to runtime (or not at all).

Yes. Which is why the Controlling_Type aspect is a better solution.

-- 
-- Stephe


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

end of thread, other threads:[~2014-08-30 15:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-28 19:21 container cursor type cannot be tagged Stephen Leake
2014-08-28 20:25 ` Randy Brukardt
2014-08-29  7:28   ` Dmitry A. Kazakov
2014-08-29  7:59     ` J-P. Rosen
2014-08-29  8:46       ` Dmitry A. Kazakov
2014-08-29 23:08     ` Randy Brukardt
2014-08-29 14:50   ` Stephen Leake
2014-08-29 23:00     ` Randy Brukardt
2014-08-30 15:16       ` Stephen Leake

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