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-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,3dbf2f325f33ce35 X-Google-Attributes: gid103376,public From: Richard D Riehle Subject: Re: Elimination of "use" clauses Date: 1999/07/18 Message-ID: <7mrjus$bet@dfw-ixnews14.ix.netcom.com> X-Deja-AN: 502284534 References: <377B5807.88B875E0@cs.york.ac.uk> <7lh74s$v36$1@nnrp1.deja.com> <7ligdq$c8q$1@nnrp1.deja.com> <7ljb4e$na9$1@nnrp1.deja.com> <7ltus1$ah1@dfw-ixnews19.ix.netcom.com> Organization: Netcom X-NETCOM-Date: Sat Jul 17 11:07:56 PM CDT 1999 X-Inktomi-Trace: sji-ca-cache 932270870 19437 209.111.213.63 (18 Jul 1999 04:07:50 GMT) Newsgroups: comp.lang.ada Date: 1999-07-17T23:07:56-05:00 List-Id: I always enjoy the thoughtful responses posted here by Dr. Duff. In article , Robert A Duff wrote: in response to my advocacy of a nested or child Ops package (see the code moved to the end of this posting) >I used to like this idea, but I've seen nasty bugs caused by it. >Imagine if that last ">" were replaced with "=" due to a cut-and-paste >error. It's hard to notice such a bug by reading the code, because as >soon as you see "package Ops is" followed by "function ">"", you already >know (or *think* you know) what comes next, so you don't read it >carefully. And when you're reading someplace else that calls "<", you >obviously think it's calling something called "<". Cut and paste errors are one of the inherent problems with renaming, especially a liberal model for renaming. I agree that one must be careful about such things. More frequently, I have seen people use ">" when then intended "<". This error is still possible with "use type". If one only exports the "<", the chance of making a mistake of ">" is reduced. >The "use type" clause is safer. Respectfully disagree. The use type clause exports visibility for every operator on a type. Now, if use type allowed a list of the operators to be restricted ... For example, use type X.T ("=", "<", "/"); one would be able to designate exactly which operators were appropriate to the use of the type. This is analogous to the "export" directive found in some other languages. >> This package has the advantage of exporting, through a use clause, only >> the operators you want unless you decide to make others explicitly >> visible. The client of the package has an easy way to achieve the >> necessary visibility. It is a better option than use type because it >> only makes visible a restricted set of operators. > >Good point. I wouldn't mind having a concise way of saying (eg) "T is >an integer type with just "+" and "-" operators. But I still prefer >"use type" to "package Ops". We agree up to a certain point. Explicit export directives would solve the problem, but that is not currently part of Ada. Again, "use type" is too broad, I think. >>... Also, it allows one >> to design new behavior for some operators while implementing others >> through a simple renames clause. > >It seems like a dangerous idea to use anything *but* a renaming, if the >operator in question is predefined. I mean, if Sweet_Tooth."=" and >Sweet_Tooth.Ops."=" do two different things, you're asking for trouble. >Maybe I misunderstood what you mean, here. The example that comes to mind is the division operator on a floating point value. Instead of implementing it via a renames in package Sweet_Tooth.Ops, I might want to design my own "/" which does additional checking of the values, raises some specialized exception, takes into account a set of tolerable ranges instead of behaving exactly as defined in the language or numerics annex. The same could be true of other arithmetic operators. Also, the "=" operator on a floating point might be designed to greater tolerances than predefined by the language. >>... With Ada 95 you could create a child package for Sweet_Tooth.Ops >> to keep it extensible. >I don't understand that point. This simply means that Sweet_Tooth.Ops could be a child package of Sweet_Tooth instead of a nested package. In that case, it is extensible with new operators as necessary. >> Ada's use clause, like the #include of the C family of languages, >> is somewhat analogous to wiring your home with uninsulated cable. > >That analogy is a bit overblown! If you want to insulate something, put >it in a package body where it belongs. And surely "use" is not in the >same category as "#include". Analogies always have their flaws. The suggestion of putting the entity into the package body is, I agree, the ideal. If this were Modula-3, that would solve the problem quite nicely. Since Ada is not designed to explicitly support opaque types, one must often use indirection to support this notion. When a "with" and "use" are used together, it is very much like removing the insulation. Although it is not quite as dangerous as the C++ #include, it is very close to it. To be sure, we still have all the issues of type conformity, semantic legalities, etc., but we also have the problem of excessive visibility. One of Ada's most positive strengths, as a software engineering language, is the separation of scope and visibility. Perhaps what is needed, in the next revision, is some additional syntax for making this feature even stronger. Maybe we really do need some kind of "export" feature so the designer of a package can be explicit about what should be allowed and what should not be. Meanwhile, the nested or child Ops package, properly designed, provides that level of control. I think it does so better than the "use type" since it restricts the set of operators available via any use clause. Richard Riehle richard@adaworks.com http://www.adaworks.com -- =========== Original Code for this Discussion ================ >Richard D Riehle writes: > >> package Sweet_Tooth is >> >> type Frozen_Dessert is private; >> type Lollipop is (OrangeIce, Fudgecicle, Chocolate_Cream); >> >> Procedure Create (F : in out Frozen_Dessert); >> -- more operations >> -- declare an Operators only package >> package Ops is >> function "=" (L, R : Lollipop) return Boolean >> renames Sweet_Tooth."="; >> function ">" (L, R : Lollipop) return Boolean >> renames Sweet_Tooth.">"; >> end Ops;