From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: a07f3367d7,7ff1de84a8945e80 X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news3.google.com!feeder1-2.proxad.net!proxad.net!feeder1-1.proxad.net!oleane.net!oleane!news.ecp.fr!news.jacob-sparre.dk!pnx.dk!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: Access types as parameters Date: Tue, 11 Aug 2009 18:41:21 -0500 Organization: Jacob Sparre Andersen Message-ID: References: <521c4843-d40f-4545-9e80-ca725e847090@h21g2000yqa.googlegroups.com> <8410fc60-9b8a-4f82-92fc-622a6bbe5931@i18g2000pro.googlegroups.com> <8880c3d0-a07f-4d4e-ac87-372014598576@d15g2000prc.googlegroups.com> NNTP-Posting-Host: static-69-95-181-76.mad.choiceone.net X-Trace: munin.nbi.dk 1250034147 20633 69.95.181.76 (11 Aug 2009 23:42:27 GMT) X-Complaints-To: news@jacob-sparre.dk NNTP-Posting-Date: Tue, 11 Aug 2009 23:42:27 +0000 (UTC) X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.5512 X-RFC2646: Format=Flowed; Original X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.5579 Xref: g2news2.google.com comp.lang.ada:7685 Date: 2009-08-11T18:41:21-05:00 List-Id: I know this is old, but it is so misguided that it needs a reply...especially as it is from someone who usually knowledgable on this forum. - RLB "Stephen Leake" wrote in message news:u63dkb12m.fsf@stephe-leake.org... ... > Most GTK subprograms do need access values; the same is true of any > system that deals with derived types at multiple levels. The only > library-level object that can hold any type in the hierarchy is a > class-wide pointer. Lists of objects must hold pointers, etc. All of the indefinite containers can hold class-wide objects. No (explicit) pointers are needed. One of the goals for the next revision of Ada is that the vast majority of reasonable data structures can be reasonably written with the Ada.Containers. In particular, the multiway tree container can be used to model almost all forms for tree structure (and many graphs as well). That should mean that the need for explicit access types will be greatly reduced when class-wide programming. Now, of course, GTK was designed for Ada 95, and those options weren't available then, so misguided choices were more justifiable. ... > A reason to use 'access Record_Type' instead of 'in Access_Type' is to > avoid explicit type conversions. This is a terrible reason: explicit conversions show when you are converting accesses from one "domain of use" to another. (I'm thinking of each named access type as a "domain-of-use". It only makes sense to have multiple named access types for a particular designated type if there are different "domains-of-use" [such as different storage pools or disjoint data structures].) The type conversions make it clear when you are converting from one "domain-of-use" to another, something that should be rare. Anonymous access types hide that, and make it essentially impossible to determine what the storage pool of an access is -- meaning that most values that pass through anonymous access cannot be deallocated even if converted to a named type (because there is no way to know if it is the *right* named type). [Technically, they can be deallocated, but the program is erroneous and may do anything.] Finally, the implicit conversions are only allow to the anonymous type. To get back to a named type, you have to go back to explicit conversions, so you don't really save anything. In your example: > Given: > > package Widget is > type Gtk_Widget_Record is ...; > type Gtk_Widget is access all Gtk_Widget_Record'class; > > procedure Show (Widget : in Gtk_Widget); > end Widget; > > package Window is > type Gtk_Window_Record is new Gtk_Widget_Record with ...; > type Gtk_Window is access all Gtk_Window_Record'class; > end Window; > > Window : Gtk_Window := ...; > > then this does not work: > > Widget.Show (Window); > > but this does: > > Widget.Show (Gtk_Widget (Window)); > > This is just annoying! > > However, if Show is declared: > > procedure Show (Widget : access constant Gtk_Widget_Record'class); > > Then Show matches any access type in the class hierarchy; > > Widget.Show (Window); > > works. Of course, Show in this case surely should be dispatching (even if the interface itself doesn't use that property) so that extensions can extend the operation, so the declaration should be: procedure Show (Widget : in Gtk_Widget); and the call should be Show (Window.all); Probably the real reason the designers of GTK made this an anonymous access parameter is to get that dispatching property. It surely has little to do with implicit conversions. [The fact that you can dispatch on access types in Ada, but only with this bizarre syntax is a highly misguided feature of the language IMHO. It was added only because of the IN OUT parameter restrictions and the insistence of some that that not being able to copy lousy C++ and Java designs directly (rather than better Ada designs not using explicit access types) would harm the language's use in some way.] Anyway, the real issue that these implicit conversions don't work in many cases that you would expect them to. For instance, inside of Show, if you need to treat the parameter as a value of GTK_Widget: Widget_List : GTK_Widget; Widget_List := Widget; -- Illegal. Anon to Named conversions not implicit! Widget_List := GTK_Widget(Widget); Indeed, the only reason (in Ada 95) why the anonymous access conversions are implicit is the obvious problem that they don't have a name! Else I think they would have in fact required a conversion. It's possible that we'd going to fix this conversion problem in the next version of Ada, but we will have to do more study to ensure that we don't introduce a show-stopping incompatibility. ... > I've been struggling with this issue in OpenToken, and settled on > using 'access Record_Type' as the best compromise. Now I just need to add > 'constant' in all the right places; that wasn't allowed in Ada 95, > when OpenToken was first written. That may have made sense in Ada 95, but now it is a terrible choice, as it forces the user to do all memory management on the objects. If you force passing access-to-objects, you cannot store the objects in a container and allow the container to do the storage management. (It also requires adding a huge amount of noise to stack-allocated objects -- the need to declare everything "aliased" and 'access on every call -- and the use of stack-allocated objects should always be a primary goal. Why OpenToken cannot be designed to usually use stack-allocated objects escapes me...) > In some cases, I have both class-wide and primitive operations: > > type Instance is abstract tagged private; > subtype Class is Instance'Class; > type Handle is access all Class; > > function Name (Token : in Instance) return String is abstract; > > -- Dispatching calls to Name > function Name_Dispatch (Token : in Class) return String; > function Name_Dispatch (Token : access constant Instance'Class) return > String; > > That gives the best of all cases, at the expense of writting more > code. Let me get this straight. You declare an extra routine with a much longer name and a complex (and expensive at runtime call-sequence) in order that you can avoid writing ".all" periodically?? That is, if you have type Any_Instance_Class is access all Instance'Class; An_Instance : Any_Instance_Class; (and appropriate visibility), you would rather write: Name_Dispatch (An_Instance); rather than Name (An_Instance.all); ??? Moreover, if you are using Ada 2005, you probably should write: An_Instance.Name And you don't even need the .all anymore! (Nor do you need "appropriate visibility"!) Talk about a lot of work for nothing. ;-) >> And if you're going to store the access parameter in a global >> structure, you'll get a runtime error if you try to store a dangling >> reference, so it's best to use a global access type so that >> accessibility level errors are caught at compile time. > > This is a problem; people keep stumbling across it. Still, you get > used to it after a while, and stop trying to pass 'access of a local > variable. One would hope that designers of Ada interfaces would talk more care for the users than to say "they get used to it after a while". That sort of ticking time bomb (that easily can be missed in unit testing!) is very adverse to the goals of safety espoused by many in this group (including me!). It has the potential of making Ada into just another programming language. Randy.