[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::languages

Title:Languages
Notice:Speaking In Tongues
Moderator:TLE::TOKLAS::FELDMAN
Created:Sat Jan 25 1986
Last Modified:Wed May 21 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:394
Total number of notes:2683

37.0. "Overloading" by TURTLE::GILBERT () Tue Oct 16 1984 18:41

This note is to solicit comments on overloading of operators/functions/names
as a programming technique.

					- Gilbert
T.RTitleUserPersonal
Name
DateLines
37.1ORPHAN::BRETTTue Oct 16 1984 21:0455
Lets define the concept so that more people can understand/participate.
Overloading is the declaration of several entities/operations with the same
identifier, in such a away that the compiler has to decide by context which
entity/operation applies.

Traditional languages, such as Fortran and Pascal, have overloading only on a
limited set of the arithmetic/boolean operators.  For instance

	program P;
	var I,J : INTEGER;
	    A,B : REAL;
	begin
	    I := I + J;		"+" adds integers
	    A := A + B;		"+" also adds reals
	end.


Ada has recently generalised this in two ways.  Firstly it allows multiple
declarations of the same procedure, with different parameter lists...


	function MAX(I1,I2 : INTEGER) return INTEGER is...
	function MAX(I1,I2 : FLOAT)   return FLOAT   is...

	-- Now BOTH are 'visible' just like the two "+" operators were in 
	-- Pascal.

Secondly it allows declarations of the 'operators'...

	function "<"( I1 : INTEGER; R1 : FLOAT) return BOOLEAN is
	begin
	    return LONG_FLOAT(I1) < LONG_FLOAT(R1);
        end;





It has a complex, but fairly intuitive, set of rules that are used to decide
which 'meaning' is correct - basically they boil down to "IF MORE THAN ONE
MEANING IS LEGAL, THE PROGRAM IS 'AMBIGUOUS', AND THE USER MUST SUPPLY MORE
CONTEXT".




My general feeling about the whole issue is (1) its a good idea, (2) it can be
abused, (3) it'll take a while to learn how to make the best use of this
ability.

Is does slow the compiler down somewhat, but not unduely.


/Bevin
37.2ERLANG::CAMPBELLWed Oct 17 1984 15:4231
This is similar to the approach used in (I'm starting to hate this
term) "object-oriented languages", especially Smalltalk, and CLU.
It makes a lot of sense.  I am a firm believer in strongly-typed,
object-oriented languages with multiple inheritance.  A simple
example of why (read on, this *is* relevant to overloading):

There are certain generic operations one would like to perform
on singly-linked lists:  insert at beginning, insert at end, delete
first element, delete last element, count elements, find element,
delete element given pointer to predecessor.  Now in ordinary
strongly-typed languages you have to define these operations once
for every kind of list you have!  If you have lists of strings,
lists of floats, lists of tasks, lists of records of type A, and
lists of records of type Z, you end up with 7*5=35 functions.
With inheritance (subclassing) you just define 7 generic list
operations, and each subtype (list of strings, for instance)
inherits these operations.

In a sense this is overloading because if I have a variable FOO
which is of type "list of strings", and I say DELETE_FIRST (FOO),
the "right" function gets called.  In a clever implementation the
code is shared too.  I propose that it is tiresome and wasteful
to make me write each generic list operation once again for each
new type of list.

Put me down in favor of overloading.  (More, in favor of subclassing
and multiple inheritance.)

- Larry Campbell
  Eastern Research Lab (Hudson)

37.3ORPHAN::BLICKSTEINWed Oct 17 1984 17:578
1.  Overloading is a strongly-typed language concept.  It has no meaning
    or place in non-strongly typed languages.

2.  Strongly-typed languages are a bad idea (in my opinion).

3.  Overloading is bad (derived from (1) and (2)).

	db
37.4SAUTER::SAUTERThu Oct 18 1984 09:133
re: .3--I think item 2 of your syllogism needs more support.  I *like* 
strongly typed languages.
    John Sauter
37.5TURTLE::GILBERTThu Oct 18 1984 19:2615
As I understand it, the difference between a typed language and a strongly
typed language is that the strongly typed language doesn't do implicit
coersions of data types.  Correct?

This being the case, I'll argue with the first point in .3's syllogism;
overloading does not require a strongly typed language, a typed language
will suffice.

Also, I prefer strongly typed languages.  There is a high nuisance value
paid when writing "system" software (compilers) to circumvent the strong
typing.  However, this is easily absorbed by large software development
efforts; smaller software efforts benefit by the additional error checking
provided by strongly typed languages.

					- Gilbert
37.6ADVAX::A_VESPERFri Oct 19 1984 10:4882
re .2 and 'subclasses': 

I love this idea also, having used SIMULA-67 where this is a
major part of the language.  It is a very powerful concept. 

SIMULA allows you to define both data storage and code
needed for a concept in one package, called a CLASS.  An
example off the top of my head (I KNOW it's wrong -- I
haven't been able to use SIMULA for years): 

    CLASS listelement;
	BEGIN
	POINTER (listelement) next;
	END;

    CLASS listhead;
	BEGIN
	POINTER (listelement) first;
	POINTER	(listelement) last;

	PROCEDURE add (le);
	    POINTER (listelement) le;

	    IF THIS listhead.last == NULL THEN
		BEGIN
		THIS listhead.first = le;
		THIS listhead.last = le;
		le.next = NULL;
		END
	    ELSE
		BEGIN
		THIS listhead.last.next = le;
		THIS listhead.last = le;
		le.next = NULL;
		END;
	    END;

	END;

	...

This is very nice, but who wants a list with nothing in it
but the pointers?  Well, you can use that definition ... 

    listelement CLASS my_data;		/* defining a sub-class */
	BEGIN
	INTEGER		x, y, z, a, b, c;
	STRING		ss, ss2, ss3;
	END;

    POINTER (listhead) my_head;
    POINTER (listelement) current;

    my_head :- NEW listhead;

    WHILE (NOT EOF (input))
	BEGIN
	current :- NEW my_data;
	current.x = 0; ...
	my_head.add (current);
	END;

and you now have the data you want in a list. 

CLASSes can be prefixed indefinately, but only one at a
time.  Thus you can have: 

	listelement CLASS d1; ...;
	d1 CLASS d2; ...;
	d2 CLASS d3; ...;

and 'd3' has the aspects of 'listelement', 'd1', and 'd2' as
well as it's own.  You can't do: 

	(listelement, listhead) CLASS new; ...;	/* ILLEGAL */

and that's a liability.  (It would be hard to implement, but
very useful).  You can get the same effect by redefining one
of the classes with the other class as prefix, but that can
be a lot of work. 

Andy V
37.7ORPHAN::BRETTFri Oct 19 1984 17:0819
There is a VERY HIGH nuisance value in designing/implementing 'system s/w' in
non-typed languages.  Namely

	it is damn near impossible to impose the typing later so
	that (strongly) typed languages can interface directly to
	the system.

Now we have a set of languages that are obviously 'main stream', it makes a
lot of sense to define all the o/s interfaces in a subset of the facilities
of
	Ada	Fortran		PL/I	Pascal


Instead there is a bunch of short-sighted people off using C or Bliss or ...
making the whole situation steadily worse, not just here at DEC but through-
out the whole computing community.

/Bevin
37.8LATOUR::AMARTINSat Oct 20 1984 12:4114
Re .6:

The keyword is "REF", not "POINTER", but that is the only obvious syntax
error I can see.  I used Simula on the -10 in '78 and loved it.

I think a reason why classes have to inherit other classes in a hierarchical
manner is because if an XYZZY is a special BAR, and a BAR is a special FOO,
you want to execute any initialization when creating an XYZZY in a specific
order (FOO, then BAR, then XYZZY).  If you don't mind introducing invisible,
anonymous types, then (FOO, BAR) CLASS XYZZY is a reasonable thing to ask for.

Has anyone reading this file used C with classes?  Is there a public-domain
(or DEC-domain) class processor available anywhere for C?
				/AHM
37.9ADVAX::A_VESPERSun Oct 21 1984 10:5113
Re .7:

Why do you claim PL/1 is in the mainstream and C is not? 
PL/1 is used mostly by IBM mainframe shops; how successful
has VAX-PL/1 been?  If anyone has access to this
information, how about a comparision (in number of sales) of
the top VMS languages? 

I am willing to bet that you can get a C compiler for more
processors / operating systems than any other language
(except maybe FORTRAN).  Anyone have hard numbers? 

Andy V
37.10WAR750::PHILPOTTMon Oct 22 1984 08:5416
I am in favour of overloading in some cases, and opposed in others:

1) I favour the concept of overloaded operators, 

2) I have on occasion found the idea of overloaded variable identifiers 
useful (ie using the same name for a real and an integer variable can 
make a program more self-documenting)

3) I am opposed to the idea of overloaded procedures, though I am aware 
that in some cases this would be implied from (2) above. ie If you 
define procedures of the same name, but with parameter lists of 
different types, then it would be acceptable in the same sense as (2) is 
acceptable, but to have different procedure bodies, performing radically 
different tasks would make it very hard to read.

	/. Ian .\
37.11HARE::GILBERTMon Oct 22 1984 12:2512
re .-1, point 3

	Overloading can be used to increase readability and greatly improve
	programming.  Consider taking the sine of some number, where the
	programer in a non-overloaded language must distinguish between f,d,g,
	or h-floating number formats, and whether the number is in radians or
	degrees (I assume that radian and degree data-types can be defined).

	You're right, function names should be identical only for conceptually
	similar operations.  With this guideline, an INSERT operation could be
	overloaded for a variety of purposes, and with very different procedure
	bodies.
37.12ORPHAN::BLICKSTEINMon Oct 22 1984 17:4732
OK, the reason why I don't like strongly typed languages (STLs) is because they
offer no advantage over loosely typed languages (LTLs).  They are if anything
a subset of LTLs.

Any LTL compiler worth it salt will give you a warning when an implicit
conversion is about to happen.  Every PL/I compiler I've ever seen (including
ours and any of IBMs) does.  Certainly any LTL compiler can be made to do
that even if it doesn't.  Thus if you don't ignore the warning messages that
say, VAX PL/I, gives you, you can effectively use PL/I as a STL.  Perhaps
another way of understanding my view is that LTLs provide fixups (which you
can choose not to use) for type mismatches, whereas STLs just punt.

For many programs, an implicit conversion is probably a bug.  Fine, watch
for the warning messages.  For many other programs, it's a needless detail
for the programmer to be concerned with.  Why not let the computer take
care of it?  As you can see, LTLs can be used more generally.

The only capability I can think of that an STL provides over an LTL is the
possibility of overloading.  So in order to support my case, I have to
demonstrate that overloading is bad:

I offer that people who support both overloading and STLs are being
inconsistent.   The principle support for STLs seems to be that the compiler
doesn't do things behind your back that aren't visible in the code.  Isn't
that exactly what overloading does?

I recognize that the intended purpose of overloading is to have one symbol
for a generic operation.   That can be very handy.  But the conclusion I
come to is that in practical usage, it makes the code hard to read (you're
not sure what's being called), hard to debug and error prone.

	db
37.13ORPHAN::BLICKSTEINMon Oct 22 1984 18:0332
Sorry (5) but overloading is only well defined in strongly typed languages.

Consider the following pseudo program:

	declare ADD as function with parameters( float);
	declare FLT as float, INT as integer;

	call ADD ( INT );

In a loosely typed languaged, the integer parameter in the example is coerced
to the expected type of the argument, float.  In a strongly typed language
the call is illegal and therefore an alternative definition of ADD may be
searched for.  They key thing here is that with overloading, binding is
done by the context (the type of the arguments supplied), but since a
loosely typed language will do an implicit conversion, that type of binding
is impossible (or at least would be inconsistent with the rest of the language).

This example, incidently demonstrates a potential problem with loosely typed
languages.   If the language above passes arguments by reference, you're in
trouble because a FLOAT temporary is going to be needed INT.  In this case,
PL/I will pass it by value, which means that if ADD assigns to it's argument,
you'll get a bug.   The solution is obvious though: give a warning message
that the argument is being passed with a dummy argument, and that's what
I believe most PL/Is will do (although the message is not required by
the standard unfortunately).

For this reason (and others), if compilers were not capable of giving warnings
for implicit conversions, I'd be a strong supporter of STLs.  LTLs can be
very error-prone without messages, but fortunately, most LTL compilers do
issue warnings.

	db
37.14TURTLE::GILBERTMon Oct 22 1984 20:2923
In (13), the language supplies the overloading on the function ADD.  There,
the function ADD is defined to operate on type "float", but can also be applied
to an "integer" operand, as the language supplies an implicit conversion.

I presume that if the function SUB were defined to operate on "integer", and
a "float" were passed to it, the language would also do an implicit conversion.
Should this be rounded or truncated?


Overloading is not incompatible with loosely typed languages.  The method for
selecting the appropriate overloaded function is to first look for an "exact"
match (of the operands types), and to then try implicit conversions of the
operands in TBS order, to find an applicable function, complaining if more than
one (or no) applicable functions are found.

For a whistle, a strongly typed language could allow the programmer to define
or modify the methods for implicitly converting from one data-type to another.


As overloading can be applied to either STLs or LTLs, the issue of strong-typing
versus loose-typing can be moved to a separate note.

					- Gilbert
37.15LATOUR::AMARTINTue Oct 23 1984 09:5024
Re .10:

2) Uh, are you speaking about using the same name for different pieces of
storage as in disjoint Algol scopes, or using the same piece of storage as
you could do with Fortran COMMON, or what?  I am not sure what kind of
coding stylism or trick you refer to.

3) I expect that in most cases where people defend overloading of procedures
or operators, the intent is that in many or most cases you won't even be
shown what the bodies of the various implementations are; the only information
to be considered is the description of the arguments the procedures expect,
and the abstract behaviour that the procedure has (insert into a set, etc).

If you mean that you won't be able to figure out what particular behaviour
to expect without a lot of hunting around and matching up variable types
with argument lists, I agree that there is certainly a danger of that.
Supposedly the more you confine overloading to generic operations that have
strong conceptual similarities, the less this is a problem.  Look at the
various switches to the DCL DELETE command, and tell me if you like or
dislike the arrangement.  It is not pure overloading in the sense that
the switches give syntactic hints as to what to do, but "DELETE" can still
delete quite a variety of things (and such deletion is probably implemented
in very different ways).
				/AHM
37.16ORPHAN::BLICKSTEINTue Oct 23 1984 12:5427
What you have described in (14) is not the way LTLs behave.

Remember that what I said was that overloaded operators are ill-defined in
LTLs, not impossible.   Overloading is undesireable for LTLs because you
will have to graft inconsistent rules to the language.  I don't think you've
fully considered the can of worms you've opened.

For example:

	DCL ADD function with parameters( G_FLOAT) ...,
            ADD function with parameters( D_FLOAT) ...,
	    I   variable with type F_FLOAT;

	CALL ADD(I); 

Which incarnation of ADD does the call bind to?  In an STL the answer is clear:
neither, it's an error.  In an LTL, it's unclear. If ADD wasn't overloaded,
this would be legal in an LTL.  Are you going to make it illegal?  (That isn't
LTL-like).  Are you going to define a "gravitational order" (F_FLOAT gravitates
to D_FLOAT before G_FLOAT)? Yuck!  Either way it's poor language design. 

So you see, overloading is NOT well defined for LTLs.  Now before you concoct a
solution to THIS problem stop and think a little more about the problem in
general.  Even if you choose to define this case by such a method, I can throw
at least 10 more at you that require similar kludges. 

	db
37.17WAR750::PHILPOTTTue Oct 23 1984 13:2315
re .15

my intent in .10 (2) was to cater for the ALGOL ideas (I am an ALGOL 68 
freak I am afraid). In particular I had in mind the situation where, for 
example you had a real variable 'x', and in some parts of the algorithm 
you want to refer to, say, an integer derived from it (say its floor 
value), which for readability only, you might wish to refer to by the 
same name - in discussing the algorithm verbally, you would probably use 
the shorthand of using the same name, (after all English is in effect an 
overloaded language).

There are other cases of course where such overloading of variable names 
is useful.

	/. Ian .\
37.18TURTLE::GILBERTWed Oct 24 1984 14:5640
When you're explaining, you're losing.  Anyhow, ....
The quoted phrases are from (16).

1. "What you have described in (14) is not the way LTLs behave."

	I've described a way LTLs *can* behave with respect to overloading.

2. "... overloaded operators are ill-defined in LTLs, not impossible."

	The "TBS" in (14), when expanded, defines which overloaded operator
	should be chosen.  The behaviour can be well-defined and consistent
	(although perhaps not intuitive, nor aesthetic).

3. "Overloading is undesireable for LTLs because you will have to graft
    inconsistent rules to the language."

	Although the rules can be made consistent, they'll probably be
	un-aesthetic, and therefore undesirable.  For example, special rules may
	be required to determine which overloaded operator should be applied,
	when the operands can be implicitly converted into various other types.

4. "Are you going to define a "gravitational order" (F_FLOAT gravitates
    to D_FLOAT before G_FLOAT)?  Yuck!"

	A "gravitional order" or "ranking" of datatypes seems the simplest of
	solutions.  Yuck.

	Furthermore, if the language allows for user-defined datatypes (atypical
	of LTLs), user-defined datatypes should be accorded the same respect as
	the "built-in" datatypes:  To take part in the "ranking";  Able to make
	use of the "built-in" operators; and able to have user-defined implicit
	conversion rules defined on them.

Although we roughly agree on points 2, 3 and 4, our conclusions differ.  This
depends on whether you consider the fact that points 2, 3, and 4 are also valid
complaints against existing LTLs, whether "+" or "ABS" or "EXP" or "INT" are
overloaded operators, and whether the same elements of language design should be
applicable to both built-in and user-defined operators, functions and datatypes.

					- Gilbert
37.19ORPHAN::BLICKSTEINWed Oct 31 1984 07:3919
I made an incorrect statement.  PL/I apparently DOES have overloaded names!
In PL/I it's called GENERIC and it looks as follows:

	DCL   FUN GENERIC(FUN_FIXED WHEN (FIXED),
			  FUN_FLOAT WHEN (FLOAT));

There's no "gravitational order", the match must be exact (which is entirely
inconsistent with the rest of the language but is preferential to the
alternatives).

This definition addresses the common objection to the ada definition which I
believe to be error-prone because it allows overloading of names that aren't
meant to be overloaded. I think the PL/I definition is highly preferable to the
ada method in that it makes overloading of names an explicit action.

I can see where this definition can be useful, but it's yet another example of
why PL/I is often referred to as the "kitchen sink" language.  PL/I is a large
collection of individually desireable language features mixed together like a
tossed salad.