comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Run-time accessibility checks
Date: Fri, 12 Dec 2008 10:21:55 +0100
Date: 2008-12-12T10:21:56+01:00	[thread overview]
Message-ID: <e60jnl0ra4tc.1hhg5aep6moxy.dlg@40tude.net> (raw)
In-Reply-To: ghs3i2$80u$1@munin.nbi.dk

On Thu, 11 Dec 2008 16:15:39 -0600, Randy Brukardt wrote:

>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote
> 
>> My solution is inheritance, disliked so much. If you want
>> a referential type to be a substitute for the target type, then the 
>> referential type simply must  inherit to the target. (We don't need "all", though it 
>> can be preserved using some intermediate referential type.)
> 
> Well, this doesn't make any sense to me at all. And the following example 
> doesn't help; you've made it the *same* type, which is definitely not what 
> you want.

No I made it having same interface, the implementation is different. You
have a wrong model in mind. Same interface does not imply same
representation / implementation.

> The result of dereferencing an access value is a *different* type, 
> with *different* operations. I don't *want* interchangability!!

Then you have what you have - an inability to assign an element in the
container, *because* it is of a different type. In my solution the
container element does not magically change its type, just because you
don't want to copy it. Why should it? The container knows how to access its
elements.

>> Because Ref_Type is not abstract, you will have to override all primitive 
>> operations of Target_Type, and assignment must be a primitive operation, 
>> and components getter/setters of, in case Target_Type were a record type, 
>> must be as well.
> 
> That sounds like a maintenance headache (any change must be replicated 
> everywhere. That became such a pain for the Claw Builder program that it 
> almost ground development on it to a halt.)

That is another issue. Ada has no good support for delegation. You should
be able to delegate Target.Operation to Ref_Type.all.Operation without
writing boring wrappers. It is not specific to this case.

>>> You certainly can't have a procedure ":=" to do assignment in because of 
>>> discrimant-dependent components.
> 
>> ":=" is a statement. What I would do is to define *two* primitive 
>> subprograms the compiler will use in order to compose *one* ":=". The 
>> first operation will determine the discriminants, the second will continue 
>> with those known.
> 
> That's not the problem; the problem is that components appear and disappear, 
> and there is no way to assign them.

I don't see any problem. All discriminants are known in the *second*
primitive operation. That allows you to write a case statement and assign
existing components.

> And there is no way in Ada to just set 
> the discriminants without giving values to the components as well; that is a 
> fundamental invariant of the language which I don't think can be changed 
> without making everything erroneous.

You don't need it. The *first* primitive operation does not deal with the
values. The idea is very simple. For each type T there is a predefined type
T'Constraint defined as a tuple of discriminants (array bounds, type tags)
of T. For example, when

   type T (X : Integer) is record
      case X is ...
      end case;
   end record;

then

   type T'Constraint (X : Integer) is null record;

Now the *first* primitive operation determines T'Constraint. The *second*
primitive operation is called either on an object with the constraints set
from the result of the *first* operation or else with a value of
T'Constraint. That is it:

   procedure Set (T : in out Object);  or
   function Set (Constraint : T'Constraint) return T;

>> Records are not iterated. If we want a container to support iterations, 
>> that must be an abstract array. It also was getter and setters:
>>    function "()" (A : Abstract_Array_Type; I : Index_Type) return 
>> Element_Type is abstract; procedure "()" (A : in out Abstract_Array_Type; 
>> I : Index_Type; E : Element_Type) is abstract;
> 
> That's not flexible enough for iteration; the index can be anything (it need 
> not have an inherent ordering; it surely cannot be restricted to a discrete 
> type) and thus just having this interface does not allow iteration.

I proposed to introduce unordered arrays long time ago.

> There also is very little chance of such an interface being supported in 
> Ada, if I read the feelings of the group well enough. One concern I've heard 
> is that there is no practical way to support this for slicing (again, 
> because the index does not necessarily have ordering). Personally, I'd give 
> up slicing for this sort of abstraction, but I don't think that will fly.

I think it is solvable. First we have to introduce abstract index types.
Ada lacks this abstraction completely. If we had index types we could make
ranges first-class citizens. That would allow to solve slicing.

> Another concern is that almost all of the existing predefined packages would 
> have to be scrapped and replaced to make any use of this (especially the 
> string packages). But people aren't willing to do that ("insufficiently 
> broken"), even if there is plenty of evidence that we could do a lot better 
> for those packages.

Why scrapped? Simply moved to the Annex J (:-))

>>> And it also isn't very flexible -- where does the Cursor of a container 
>>> go??
> 
>> To me to the recycle bin. *BUT* there is no any problem with cursors, 
>> absolutely. A cursors is a pair. The first component is a type derived 
>> from the container's interface (a reference to the container), the second 
>> component is the container's index. Done!
> 
> The cursor is the index in the model you have here. And it already is a pair 
> (container, access to something).

To me index is an instance of an abstract ordered or unordered index type.
Its values are unrelated to any specific container. Cursor is an index + a
specific container.

> Not sure what you dislike about them; 
> they've have the same semantics if not the same name. (I was talking about a 
> record selector interface, which makes more sense for getting individual 
> elements.) 

Referential semantics is what I dislike in cursors. Cursor is a dressed
pointer. It is very difficult to use it in concurrent/volatile environment.
It is inherently unsafe, what happens with it upon container update? Where
is that described? How to prevent update when a cursor is still there. And
so on, and so forth. Cursor is a bad, crippled thing.

> What *cannot* be the case is that the index is required to be 
> some sort of discrete type.

Right, that must be an abstract interface, which any type could implement.

> That would require a map to translate said index 
> into some sort of access to the actual element. But that would be silly, 
> especially for map containers (you'd have to go through two maps to find 
> anything, and for what??)

You have pointer model in mind. But there is no pointers in my world. There
is a setter operation. The setter takes an index argument, it is not my
business to look into the implementation of.

> But the real problem in all of these things you've suggested is that they 
> are all technically by-copy for reading. If that is all you want, the 
> existing Ada containers do that just fine. The problem is that if the 
> elements are large, copying them may be very expensive, so a by-reference 
> access method is reading. That's the core of the problem I'm trying to 
> address (because I think there is a chance that people will view it as 
> significant enough to deal with). Functions returning values of a type *do 
> not* provide any solution to that (and cannot).

This makes no sense to me. Reading is not an operation. If a primitive
operation of Element_Type has to be called on an element of Container_Type
specified by Index_Type, that is not "reading." If you mean "functional"
appearance of "getter," them firstly, it is not obvious why the getter is
to be used to achieve the goal, and secondly return by reference is marked
as "solved" in Ada 2005. Those Pickwickian functions were praised for that,
or? (:-))

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



      parent reply	other threads:[~2008-12-12  9:21 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-06 10:15 Run-time accessibility checks (was: Construction initialization problem) Dmitry A. Kazakov
2008-12-06 17:10 ` Ludovic Brenta
2008-12-07  8:44   ` Run-time accessibility checks Dmitry A. Kazakov
2008-12-07 14:56     ` Ludovic Brenta
2008-12-07 19:22       ` Dmitry A. Kazakov
2008-12-11  1:03     ` Randy Brukardt
2008-12-11  9:08       ` Dmitry A. Kazakov
2008-12-11  0:55 ` Run-time accessibility checks (was: Construction initialization problem) Randy Brukardt
2008-12-11  9:48   ` Run-time accessibility checks Dmitry A. Kazakov
2008-12-11 11:21     ` Georg Bauhaus
2008-12-11 11:40       ` Dmitry A. Kazakov
2008-12-11 22:15   ` Run-time accessibility checks (was: Construction initialization problem) Randy Brukardt
2008-12-11 22:31     ` Randy Brukardt
2008-12-13  0:49       ` Randy Brukardt
2008-12-13  9:06         ` Run-time accessibility checks Dmitry A. Kazakov
2008-12-16  1:53           ` Randy Brukardt
2008-12-16  9:28             ` Dmitry A. Kazakov
2008-12-16 22:21               ` Randy Brukardt
2008-12-17  8:54                 ` Dmitry A. Kazakov
2008-12-12  9:21     ` Dmitry A. Kazakov [this message]
replies disabled

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