Limited use for limited with?

Limited use for limited with?

Post by Alex R. Mo » Wed, 29 Sep 2010 18:04:41



Completely unhelpful on my part -- but my limited (ha) attempts at using
"limited with" have been a failure. I'm no expert at OO or C++, like you, so
I can't bring any expertise to the table.

Something that can be of interest in this context is a discussion that
happened not too long ago (half a year?) in some mailing list -- I thought
it was the GAP one, but combing the topics I can't find it. People trying to
do "proper" OO with the new Ada features was complaining about some
unavoidable quirks. The discussion point was on the truth of "unavoidable".
I'm failing at locating it, if it rings some bells for someone...

Alex.
 
 
 

Limited use for limited with?

Post by Ludovic Br » Wed, 29 Sep 2010 18:18:05

aciej Sobczak wrote on comp.lang.ada:
>> > rocedure Do_Something (X : in out Object) is abstract>
> end Objects>
> In such cases I routinely define the XYZ_Access type and later use i>
> wherever pointers to class-wide XYZ are needed>
> Now consider a package that uses the above in a limited way (pu>
> intended), where only pointers to class-wide type are needed>
> with Objects>
> package Object_Users i>
> procedure Use_Object (X : Objects.Object_Acces>);> >
> end Object_Use>s;> >
> The problem is that is some cases it would be more convenient (or j>st
> more self-documenting from the design perspective) to do limited w>th
> instead, but unfortunately this makes Object_Access unavailable. It>is
> OK to use anonymous access type, at least in some cases like he>e:> >
> procedure Use_Object (X : access Objects.Object'Cl>ss>;
>
> but I find that uncomfortable - after all, the proper access ty>e is
> already defined for exactly this pur>os>.
>
> In such cases, where the design intent is pretty clear (pass a>ound
> references to Objects) I find that limited with does not really >ring
> the functionality that it is supposed to provide. In some>more
> involving cases I was forced to introduce additional and compl>tely
> artificial packages, where limited with would be a perfect>fi>.
>
> Any thoughts on this?

I generally think twice or three times before declaring an access type
in the same package as the object type. In fact, I think twice before
declaring any access type at all :) To me, an access type makes the
package unclean.

Since, in Ada, all objects of tagged types are passed by reference and
since Ada has class-wide types, you do not need any access type to
achieve pass-by-reference semantics or dynamic dispatching. This
leaves dynamic memory allocation as the only remaining justification
for access types. If I need dynamic memory allocation, I'd consider
using a container (possibly indefinite) before introducing an access
type. By this reasoning, a general (!) class-wide access type to an
interface (as opposed to a tagged type) may not be justified as you're
never going to dynamically allocate interfaces, only tagged types that
implement the interface.

If, after all these musings, I decide that an access type is really
necessary after all (perhaps because I'm writing my own container),
then I usually declare it where I need the access type, i.e. in
another unit, possibly even in the body. Like so:

package Objects is
type Object is interface;
procedure Do_Something (X : in out Object) is abstract;
end Objects;

with Objects;
procedure Client is
type Object_Access is access Objects.Object'Class; -- not "access
all"
O : Object_Access := new Objects.Object;
begin
...
end Client;

Taking this approach further, I can declare the access type in a
nested scope. When the access type goes out of scope, all objects
allocated through it are deallocated. This is a form of automatic
garbage collection.

If you take this approach, your "limited with" problem will disappear.
As an extra bonus, you can make your package Objects Preelaborated, or
even Pure.

Ludovic Brenta.

 
 
 

Limited use for limited with?

Post by Vadim Godu » Wed, 29 Sep 2010 18:32:07


It is how limited with is defined. Ada2012 should relax rules to make
limited with more useful.
 
 
 

Limited use for limited with?

Post by stefan-luc » Wed, 29 Sep 2010 20:34:50


[...]
Compiler doesn't like Objects.Object_Access:


[...]
Anymous access works, but is ugly:


[...]

Not an answer to your question -- but what requirements force you to use
an access type at all? To me, the most natural would be to write
"X: in out Objects.Object":

limited with Objects;

package Use_Objects is

procedure Use_1(X: access Objects.Object); -- compiles fine
procedure Use_2(Y: in out Objects.Object); -- compiles fine
procedure Use_3(Z: Objects.Object_Access); -- invalid use of incomplete
type

end Use_Objects;

--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------
 
 
 

Limited use for limited with?

Post by stefan-luc » Wed, 29 Sep 2010 22:15:27


Sorry, what I wanted to write is

procedure Use_2b(Y: in out Objects.Object'Class);

this also compiles fine.




--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------
 
 
 

Limited use for limited with?

Post by stefan-luc » Wed, 29 Sep 2010 22:15:27


Sorry, what I wanted to write is

procedure Use_2b(Y: in out Objects.Object'Class);

this also compiles fine.




--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------
 
 
 

Limited use for limited with?

Post by Dmitry A. » Wed, 29 Sep 2010 22:45:53


The benefit is clear - no access types.


You should register the object itself rather than its pointer. Use a
constructing function which registers the object by placing it in a list or
do an explicit call to Register. Upon finalization Finalize would remove it
from there. The type of the object must be limited of course. This is the
schema I am using.


I tend to avoid "all" everywhere I can.

--
Regards,
Dmitry A. Kazakov
http://www.yqcomputer.com/
 
 
 

Limited use for limited with?

Post by Robert A D » Thu, 30 Sep 2010 00:54:34

Ludovic Brenta < XXXX@XXXXX.COM > writes:


Those objects are finalized, but they are not deallocated in
most implementations, unless you use Storage_Pool or
Storage_Size. I think that's a good thing.

- Bob
 
 
 

Limited use for limited with?

Post by Adam Benes » Thu, 30 Sep 2010 01:55:47

n Sep 28, 12:37m, Maciej Sobczak < XXXX@XXXXX.COM > wrote:
>> > rocedure Do_Something (X : in out Object) is abstract>
> end Objects>
> In such cases I routinely define the XYZ_Access type and later use i>
> wherever pointers to class-wide XYZ are needed>
> Now consider a package that uses the above in a limited way (pu>
> intended), where only pointers to class-wide type are needed>
> with Objects>
> package Object_Users i>
> procedure Use_Object (X : Objects.Object_Acces>);> >
> end Object_Use>s;> >
> The problem is that is some cases it would be more convenient (or j>st
> more self-documenting from the design perspective) to do limited w>th
> instead, but unfortunately this makes Object_Access unavailable. It>is
> OK to use anonymous access type, at least in some cases like he>e:> >
> procedure Use_Object (X : access Objects.Object'Cl>ss>;
>
> but I find that uncomfortable - after all, the proper access ty>e is
> already defined for exactly this pur>os>.
>
> In such cases, where the design intent is pretty clear (pass a>ound
> references to Objects) I find that limited with does not really >ring
> the functionality that it is supposed to provide.

I'd recommend that you look at the example in the AI (AI95-217-6):

http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ais/ai-50217.txt

and in particular the !example section. The example there shows two
packages that depend on each other, using "limited with", but neither
package declares an access type that is an access to a type in the
same package. Instead, the Employees package declares a named access
type whose designated type is in the Departments package; and the
anonymous access types in both packages all refer to types in the
other package. So the code that you find "uncomfortable" really *was*
the way it was supposed to work, I think.

I can understand that this solution may not have given you a way to
express things the way you might have preferred. But doing things
"perfectly" was, I believe, unfeasible. If you look at the !
discussion part of this AI, you'll realize how much effort the ARG put
into trying to come up with a solution that would provide a reasonable
way to solve a real problem while doing so in a way that could be
implemented feasibly by compilers, and in a way so that precise
language rules could be written and that problems that could arise
from using different combinations of features were addressed. (Note:
I am not an ARG member and was not part of this effort.) And then you
have to multiply all that effort by seven, because "limited with" was
just one of *seven* different proposed solutions to the mutual
dependence problem, and all of them received extensive consideration.

So it really rubs me the wrong way to see comments---not from you, but
from someone else---such as "Ada2012 should relax rules to make
limited with more useful." Perhaps it's because I'm reaching the
Grumpy-Old-Fart-In-Training phase of my life. But given the amount of
work the ARG put into this over a number of years, can't we at least
assume that they did the best they could to make it as useful as they
could, and that whatever rules are there that you don't like are there
for a very good reason? Jeesh, now I sound like I'm talking to my
teenager. Definitely headed for G.O.F. at full speed.

I'm certainly not opposed to people wanting changes
 
 
 

Limited use for limited with?

Post by Robert A D » Thu, 30 Sep 2010 02:31:54

Adam Beneschan < XXXX@XXXXX.COM > writes:


Well, ahem, the ARG actually IS considering some changes to
make 'limited with' more useful. Sorry, I don't remember
the AI number(s).


As a member of ARG, I'd like to point out that "lots of hard work"
does not always produce good solutions. Maybe we all were
confused, and a fresh look would produce something better.

As always, the primary difficulty is remaining compatible
with early versions of the language. And the second one
is making it implementable by existing compilers, which
were of course designed without knowing about whatever
new rules the ARG is cooking up. Without those two
concerns, fixing the "cyclic imports" problem is easy.


;-) ;-)


Sure, it's a good idea to look at previous work in the area.
Don't take it as The Ultimate Truth, though.

- Bob
 
 
 

Limited use for limited with?

Post by Adam Benes » Thu, 30 Sep 2010 04:24:42

On Sep 28, 10:31m, Robert A Duff < XXXX@XXXXX.COM >


Well, I see some Binding Interpretations related to "limited with".
Most of them seem to be adding missing rules. I didn't see any AI's
that would relax any rules, and nothing that would make any changes to
the design or have any effect on the feature's usefulness. Unless, of
course, there are some AI's that have been assigned but haven't yet
made it onto the website. (There aren't any AI12's yet, I hope??)

I suppose my rant was somewhat over the top. Sure, ARG makes
mistakes, and it's entirely possible that they started off in a wrong
direction and kept going that way. Still, there just seems to be
something wrong when one party does a lot of work trying to figure out
what all the issues are and come up with the best solution they can,
and someone else who doesn't understand all the issues says too
facilely, "There's a flaw. You should change it." (I'm not talking
about minor and easily fixable flaws like wording errors, some of
which I reported, but "flaws" that necessarily arise because the
designers had to make some compromises and trade-offs.) I'm not sure
why I'm so sensitive to this, particularly since I didn't do any of
the work on this feature, but I am.

-- Adam
 
 
 

Limited use for limited with?

Post by Vadim Godu » Thu, 30 Sep 2010 05:32:23


May be "should" is wrong word, I am sorry for confusion, but this
extension is in Amendment 2012 right now, see

http://www.yqcomputer.com/

which allows to use incomplete type as type of parameter of
subprogram, so it covers original issue exactly.
 
 
 

Limited use for limited with?

Post by Adam Benes » Thu, 30 Sep 2010 06:32:49


My apologies. I guess I misunderstood you.

-- Adam
 
 
 

Limited use for limited with?

Post by Maciej Sob » Thu, 30 Sep 2010 07:04:28


> Dispatcher : Dispatchers.Handler'C>ass;
> Config : AWS.Confi>.O>ject);
>
> Personally it is the one I prefer. Why do you not like it?

See my answer to Dmitry for code example. The above construct, by
implicitly leaking references out of its execution, obstructs the
scoping of object l>f>time.

> > 1. Object is an interface type for the callback th>t>will be
> > implemente> >y user.
> > 2. Object_Access is a type that will be used for declaring a>d>passing
> > around callback references. I don't want everybody to define>t>eir own
> > types for what is a common func>io>ality.
>
> I don't think this functionality is that common; ideall> the only
> things you have to do with such references is record>them in a
> registry and then dereference them to call the callbacks. Yo> wouldn't
> "pass around" such references very often, I think. Especial>y if your
> callbacks are allocated at elaboration and not dynamica>ly on the
> heap.

That's right. Still, I need to express it somehow and I think that
having an explicitly defined access type is a good practice.
Unfortunately it does not seem to be compatible with the "limited
with" >eature.

> I would probably use an instance of Ada.Containers.Indefini>e_Vectors
> or Indefinite_Doubly_Linked_Lists to hold an ordered list>of class-
> wide callback objects. Is that the language feature you we>e looking
> for? Granted, such a container would duplicate the callba>k objects
> ("functors") in memory; using access values would avoid that.

Exactly, but copying is not the only problem. There are also
dependencies.
Note that my construct is not dependent on Ada.Containers and it
allows the user to write programs without any use of dynamic memory.
It is perfectly possible to create a callback object at the package
level or local in a sub>rogram.

> I would define the access type in the package that d>fines the
> registry of callback obj>ct>, e.g.
>
> limited wit> Objects;
> package R>gistry is
> ype Callback is access all Objects.Ob>ect'Class;
> rocedure Register (C : i> Callback);
> rocedure Call_All_Callbacks_In_Regist>ation_Order;
> end Registry;

Interesting. I will have to meditate on this possibility.

Maciej Sobczak * http://www.yqcomputer.com/
 
 
 

Limited use for limited with?

Post by Ludovic Br » Thu, 30 Sep 2010 15:03:38

Maciej Sobczak writes on comp.lang.ada:

No, because this is Ada :)

Suppose Register does something like (where Registry is a suitably
defined indefinite vector):

procedure Register (X : in Object'Class) is
begin
Registry.Append (X);
end Register;

This does copy a "hidden" reference to X into the Registry, it copies X
itself (i.e. deep copy). So there is no leak and the construct is safe.
Not so with explicit access values.

--
Ludovic Brenta.