[comp.lang.ada] Limited Use Clause

brian@telesoft.UUCP (Brian D. Nettleton @spot) (12/06/88)

Mike Glasgow of IBM asked me to post this idea here as he doesn't
have access to this network.

Mike and I discussed yet another change to Ada for Ada-9x, the
addition of a "limited" use clause.  This clause would allow
direct visibility of only the implicit infix operators of a visible part
of a particular package.  I do beleive this request does probably
fall into Stanley Allen's reference to "feature junkies" but that
still doesn't stop me.  The syntax might go something like (included
here only for example, I don't care too much about what words are
chosen):

  with xyz;
  ...
  use limited xyz;
  ...

As more of a maintainer of code than a developer (much of my work
involves porting and integrating other peoples code) I'm certainly
aware of how horrible use clauses can be when your looking at someone
else's code.  Therefore I agree with the coding standard Mike's project at
IBM is using which does not permit any use clauses.  I also agree with
Mike that the restriction causes unnecessary problems when you define
a derived type of say integer and then using this derived type and it's 
associated implied operators is a real pain with lots of extra "noise" 
code (i.e. renaming "=" and "+" over and over again even though they have 
the "standard" Ada definition).

Brian Nettleton
TeleSoft

- These ideas are my own and not necessarily that of my employer, etc...

tynor@pyr.gatech.EDU (Steve Tynor) (12/06/88)

In article <8812060022.AA26972@ucsd.edu> brian@telesoft.UUCP (Brian D. Nettleton @spot) writes:
>addition of a "limited" use clause.  This clause would allow
>direct visibility of only the implicit infix operators of a visible part
>of a particular package.  I do beleive this request does probably
...
>code (i.e. renaming "=" and "+" over and over again even though they have 
>the "standard" Ada definition).

But why limit this to only infix operators? How about borrowing an idea 
from Modula2?

 	with XYZ;
 	use XYZ."=", XYZ."/=", XYZ.PUSH, XYZ.POP;
 	package ...

I agree that having to either rename or explicitly use XYZ."=" (A, 1) is a
pain and tends to confuse the code more than clarify it.  

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Progress means replacing something wrong with something more subtly wrong.
                     
    Steve Tynor
    Georgia Tech Research Institute
    tynor@gitpyr.gatech.edu

rracine@AJPO.SEI.CMU.EDU (12/07/88)

Yet again the "use" clause is maligned.  I did not get the author or the
posting to include here, but the jist of the comment is that the 'use'
clause should not be used (no reasons were given) and a more specific
kind of 'use' clause should be available in Ada 9x.

That is beginning to be the same as the statement "Ada tasking is too slow."
People have said it so long (since it used to be true) that it is accepted
without any arguments.  Why not use the unrestricted 'use'?  The only
reason I have heard that can not be refuted is that it makes it hard to tell
where to find things in source code.  That argument is not a language issue,
however.  It is a Programming Support Environment issue.  The compiler
knows where the various procedures are declared.  Why can't it give us a
cross-reference listing at the end of each compilation?  

In the meantime, at least DEC has provided some tools that give some of
this functionality, and I believe that there are some PC-based tools that 
allow one to find references to identifiers.

Saying "Don't use 'use'" tells me a lot about a project.  It is not using
a sufficient APSE.  It has people who complain about Ada, since they 
probably have difficulty reading their code.  And they are probably behind
schedule, for similar reasons.

I hope this generates some discussion.

Roger Racine
C. S. Draper Laboratory, Inc.

tynor@pyr.gatech.EDU (Steve Tynor) (12/07/88)

In article <8812061626.AA13093@ajpo.sei.cmu.edu> rracine@AJPO.SEI.CMU.EDU writes:
>without any arguments.  Why not use the unrestricted 'use'?  The only
>reason I have heard that can not be refuted is that it makes it hard to tell
>where to find things in source code.  That argument is not a language issue,
>however.  It is a Programming Support Environment issue.  The compiler
>knows where the various procedures are declared.  Why can't it give us a
>cross-reference listing at the end of each compilation?  
...
>Saying "Don't use 'use'" tells me a lot about a project.  It is not using
>a sufficient APSE.  It has people who complain about Ada, since they 
>probably have difficulty reading their code.  And they are probably behind
>schedule, for similar reasons.
>
>I hope this generates some discussion.

It will from me anyway. I don't know what types of Ada projects you've
worked on or how sophisticated your ASPE is, but my experience is based on
the Alsys and DEC/ADA compilers and a project involving >60 packages.  We
adopted a 'no use' policy several months ago due to the unreadability of the
code. You say that the argument "is not  a language issue, however.  It is a
Programming Support Environment issue". Why? I thought that one of the
objectives of Ada was to define a portable, easily understood language where
dependencies are explicit.  Why rely on a non-standard ASPE to solve that
problem?  As you've alluded to, most Ada programming houses do not have
access to very sophisticated ASPEs.

BTW, my experience with the DEC/SCA is that it is so slow, it is rarely
worth the effort.  For a simple question of "is this procedure PUSH from
package X, Y or Z", it'd much rather be able to answer the question by
making explicit use of X.PUSH in the source than requiring the code reader
(probably _not_ the author, remember) to "play Mr. Compiler" and figure out
which one is getting referenced (a job made all the more difficult with
overloading...) So why not give the programmer more control over the 
"use" clause? Just because I want explicit qualified names for the
PUSH procedure, doesn't necessarily mean I need it for "=", or "PUT",
or whatever.  As it stands, it's all or nothing.

Also, for your information, I'm not "one of those people who complain about
Ada". I may have specific complaints/suggestions, but I think that,
overall, it's a terrific language.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
You can't settle an issue if you keep avoiding the questions...
                     
    Steve Tynor
    Georgia Tech Research Institute
    tynor@gitpyr.gatech.edu

peirce@claris.com (Michael Peirce) (12/07/88)

In article <8812061626.AA13093@ajpo.sei.cmu.edu> rracine@AJPO.SEI.CMU.EDU writes:
>Yet again the "use" clause is maligned.
>
>That is beginning to be the same as the statement "Ada tasking is too slow."
>People have said it so long (since it used to be true) that it is accepted
>without any arguments.  Why not use the unrestricted 'use'?  The only
>reason I have heard that can not be refuted is that it makes it hard to tell
>where to find things in source code.  
>allow one to find references to identifiers.
>
>I hope this generates some discussion.
>
>Roger Racine
>C. S. Draper Laboratory, Inc.

OK, I'll bite.  The project I worked on had a "NO USES" rule.  We did this
for readability and maintainability reasons.  Having a routine referred to
as PKG.PROC made it perfectly unambiguous.  It wasn't a matter of not having
cross references at the end of a listing (the DEC compiler we were using
had a way to get these).  The only complaint we really heard from people
was about the "problem" with having to explictly rename the "=" operator
and such.

I'd support the "NO USES" rule on another Ada project without reservations.

-- michael

leake@cme.nbs.gov (Stephe Leake) (12/08/88)

In article <6910@pyr.gatech.EDU> tynor@pyr.gatech.EDU (Steve Tynor) writes:

   But why limit this to only infix operators? How about borrowing an idea 
   from Modula2?

	   with XYZ;
	   use XYZ."=", XYZ."/=", XYZ.PUSH, XYZ.POP;
	   package ...

I vote for this one. Many times I "use" a package just to get "=",
although the package defines much more. Allowing the "use" to apply to
specific items (types as well as subprograms; indeed, any legal name?)
would definitely enhance readability.

Stephe Leake 	(301) 975-3431 		leake@cme.nbs.gov
National Institute of Standards and Technology
(formerly National Bureau of Standards)
Rm. B-124, Bldg. 220
Gaithersburg, MD  20899

leake@cme.nbs.gov (Stephe Leake) (12/08/88)

In article <8812061626.AA13093@ajpo.sei.cmu.edu> rracine@AJPO.SEI.CMU.EDU writes:

   ... Why not use the unrestricted 'use'?  The only
   reason I have heard that can not be refuted is that it makes it hard to tell
   where to find things in source code.  That argument is not a language issue,
   however.  It is a Programming Support Environment issue.  The compiler
   knows where the various procedures are declared.  Why can't it give us a
   cross-reference listing at the end of each compilation?  

   ... Saying "Don't use 'use'" tells me a lot about a project.  It is not using
   a sufficient APSE.  It has people who complain about Ada, since they 
   probably have difficulty reading their code.  And they are probably behind
   schedule, for similar reasons.

I agree to some extent. A good APSE is essential. On the other hand,
many features of Ada are for the purpose of encouraging
maintainablity, so why not add one more, if it's not too hard? Any
APSE tool is bound to be (slightly) harder to use than an editor, so
having readable source code is a good start.

Stephe Leake 	(301) 975-3431 		leake@cme.nbs.gov
National Institute of Standards and Technology
(formerly National Bureau of Standards)
Rm. B-124, Bldg. 220
Gaithersburg, MD  20899

leake@cme.nbs.gov (Stephe Leake) (12/08/88)

In article <7311@claris.com> peirce@claris.com (Michael Peirce) writes:

   ... The only complaint we really heard from people
   was about the "problem" with having to explictly rename the "=" operator
   and such.

If I go to all the effort to define operators for an abstract type
(say matrices), why should everyone have to rename them? The problem
is not with use clauses; the problem is with adequate managment. It is
much easier for managers to say "NO!" than to say "Well, I guess I
have to make a reasonable decision in each case". Judicious use of use
clauses definitely makes code more readable; injudicious use is bad.
What is required is careful thought, not automatic reactions.

Stephe Leake 	(301) 975-3431 		leake@cme.nbs.gov
National Institute of Standards and Technology
(formerly National Bureau of Standards)
Rm. B-124, Bldg. 220
Gaithersburg, MD  20899

bs@augusta.UUCP (Burch Seymour) (12/09/88)

Another believer. I was involved in a medium sized project in which we
used the 2 step approach. Build a prototype as the means of studying
the design requirements, then build the real thing. In the prototype we
kind of hacked away using use clauses with abandon. When it came time
to go back and clean everything up, I realized that even though I had
written the code I had difficulty finding routines, and especially
global data items, because there were so many. As a result, I removed
all the use clauses and used explicit references.

And I also agree to the limited use idea. I did have a few instances of
having to declare an "=" operator. I don't think that causes a great
deal of ambiguity when defaulted.

-bs-

sommar@enea.se (Erland Sommarskog) (12/11/88)

Steve Tynor (tynor@pyr.UUCP) writes:
>But why limit this to only infix operators? How about borrowing an idea 
>from Modula2?
>
> 	with XYZ;
> 	use XYZ."=", XYZ."/=", XYZ.PUSH, XYZ.POP;
> 	package ...

The problem is that the specifications above are not necessarily
unique. So you have to write:
   use XYZ."="(a, b : XYZ_type), XYZ.Push(x : some_type) ...
which quickly gets very verbose.

The original idea that there should be method for making only
infix operators directly visible seems attractive to me.
    A := B My_type."+" C
looks really ugly. 
  As for those who wanted the APSE to handle the problems with USE:
The code I want to read is the code I am to maintain. I prefer not
having to look up cross-reference lists for every name I meet. 
(Particulary cumbersome if you read the program on the Underground
on your way home.)

Let me also add that you have to have your USE clause in the head
of the package. A USE clause can appear in any declarative section.
A local USE is not so confusing as a global one.
-- 
Erland Sommarskog
ENEA Data, Stockholm
sommar@enea.se
"Frequently, unexpected errors are entirely unpredictable" - Digital Equipment

tynor@pyr.gatech.EDU (Steve Tynor) (12/12/88)

In article <4154@enea.se> sommar@enea.se (Erland Sommarskog) writes:
>Steve Tynor (tynor@pyr.UUCP) writes:
>>But why limit this to only infix operators? How about borrowing an idea 
>>from Modula2?
>> 	with XYZ;
>> 	use XYZ."=", XYZ."/=", XYZ.PUSH, XYZ.POP;
>> 	package ...
>The problem is that the specifications above are not necessarily
>unique. So you have to write:
>   use XYZ."="(a, b : XYZ_type), XYZ.Push(x : some_type) ...
>which quickly gets very verbose.

This is going one step further than I suggested. I'm not convinced that it's
truly necessary. I still think importing identifiers (if they're overloaded
you get all of them) would be a useful, relatively easily implemented
addition to the language.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Progress means replacing something wrong with something more subtly wrong.
                     
    Steve Tynor
    Georgia Tech Research Institute
    tynor@gitpyr.gatech.edu

sommar@enea.se (Erland Sommarskog) (12/18/88)

Steve Tynor (tynor@pyr.UUCP) first said:
>>> 	with XYZ;
>>> 	use XYZ."=", XYZ."/=", XYZ.PUSH, XYZ.POP;
>>> 	package ...

I said:
>>   use XYZ."="(a, b : XYZ_type), XYZ.Push(x : some_type) ...

Then he said:
>This is going one step further than I suggested. I'm not convinced that it's
>truly necessary. I still think importing identifiers (if they're overloaded
>you get all of them) would be a useful, relatively easily implemented
>addition to the language.

Of course a matter of taste, but I think mentioning a name and getting 
all subprograms with that name is a very non-Ada way of approaching
things. In Ada a subprogram *is* identified by its name and its parameter
list.
-- 
Erland Sommarskog
ENEA Data, Stockholm
sommar@enea.se
"Frequently, unexpected errors are entirely unpredictable" - Digital Equipment

dik@cwi.nl (Dik T. Winter) (12/18/88)

In article <4168@enea.se> sommar@enea.se (Erland Sommarskog) writes:
 > Of course a matter of taste, but I think mentioning a name and getting 
 > all subprograms with that name is a very non-Ada way of approaching
 > things.
But exactly the same happens with pragma INLINE.
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

tynor@pyr.gatech.EDU (Steve Tynor) (12/19/88)

In article <4168@enea.se> sommar@enea.se (Erland Sommarskog) writes:

>>>> 	use XYZ."=", XYZ."/=", XYZ.PUSH, XYZ.POP;

>>>   use XYZ."="(a, b : XYZ_type), XYZ.Push(x : some_type) ...

>>This is going one step further than I suggested. I'm not convinced that it's
>>truly necessary. I still think importing identifiers (if they're overloaded
>>you get all of them) would be a useful, relatively easily implemented
>>addition to the language.

>Of course a matter of taste, but I think mentioning a name and getting 
>all subprograms with that name is a very non-Ada way of approaching
>things. In Ada a subprogram *is* identified by its name and its parameter
>list.

I took as my precedent the INLINE pragma.  I can say:
   pragma INLINE (PUSH);
but I can't say:
   pragma INLINE (PUSH (x : some_type));

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
No problem is so formidable that you can't just walk away from it.
                     
    Steve Tynor
    Georgia Tech Research Institute
    tynor@gitpyr.gatech.edu