[net.lang.mod2] extensions, a modest proposal

BUDDENBERGRA@USC-ISI.ARPA (Rex Buddenberg) (02/25/86)

Since overloading is deemed evil (which may indeed be true), why
not remove the discussion from the realm of language definition
entirely.  Wirth did this in M2 for I/O by exiling the subject
to auxiliary modules.  Maybe we should do the same with all
the operators, not just the ones we wish to overload...
-------

nagler%orb@SUN.ARPA (Rob Nagler) (02/25/86)

Infix arithmetic is an attempt to simulate mathematics (which we all
know computers don't do very well).  One could argue that the infix
operators should extend to arrays, but APL certainly has its readability
problems.  I like lisp, but M2 isn't Lisp.  There isn't much rational
for keeping infix operators except for history and pseudo-upward
compatibility.

Overloading.  Here is my main argument against overloading:

	Text_IO.Put( s );

is legal (if "s" is an array of char) and so is 

	Text_IO.Put( s[0] );

This is a particularly simple example, but you get the drift.  To me 
this eliminates the main feature of structured languages: type checking
(or assertion verification, if you like).  If you don't care about losing
type checking, then I suggest you program in something like Smalltalk or
Lisp.  Why do you think Wirth put BYTE (formerly, WORD) in the module 
SYSTEM?  It is a major loophole (which is how you can get your overloading
of prefix operators by the way).

Rob

ark@ut-sally.UUCP (Arthur M. Keller) (02/27/86)

I beg to differ with my esteemed colleague, Mr. Rob Nagler, about the
interaction between overloading (and generics, for that matter) and
strong type checking.  My comments here apply to the issues in general
without reference to the particular language.

Without overloading and generics, strong type checking is much easier
as there is no possible ambiguity.  With overloading, the correct
procedure is used by a resolution process that uses strong type
checking.  (I don't believe overloading can be resolved at compile
time without strong type checking.)  With overloading, controlled
generic capability can be achieved.  Why would anyone want that?
Well, would you want to have to distinguish between + for integer and
+ for reals?  Would you want to have to invent unique names for each
procedure that did an equivalent thing to its data type?  I see
nothing wrong with Mr. Nagler's example.  In fact, I like it because I
wouldn't want to have to remember to use (say) PUT-ARRAY instead of
PUT.  Note that even with overloading, all the parameters have to
be compatible with exactly one procedure spec.  In the + example above,
that could mean precluding adding an integer to a real, if so desired.

In my point of view, the main benefit of strong type checking is
compile-time versus run-time checking.  Since overloading is resolved
completely at compile-time, I don't see how it is incompatible with
strong type checking.  Some generic capability (such as that in Ada)
is equivalent to a compile-time expansion of the generic package as if
it were a macro, and then using overloading to resolve it.  This too
is compatible with strong type checking, although the generic package
usually cannot use any features not common to all potential types for
the generic (i.e., a type for a generic must support all the operators
and procedures needed by the generic package).  A true generic would
have the capability of deciding what to do based on the type.  If done
at run-time, this is clearly not compatible with strong type checking.
If done at compile-time, you can use compile-time expansion as if the
generic package were a macro with macro conditionals.  In some sense,
overloading without generics can be thought of as a limited collection
of macro expansions of the generic that used macro conditionals.

---

Sometime, when I'm in a flaming mood, maybe I'll talk about sinister
functions (i.e., functions that go on the left) and their relationship
to the generalization of array indexing as locating an item in a
structure.  (That is, why shouldn't retrieval and storage into any
structure have the syntactic nicety of arrays; and how can I replace
an array with a complex data structure (i.e., if the array is sparse)
without having to modify the code using the array.)  I doubt if this
is the right audience.  Constructive comments on where to send this,
as well as expressions of interest in discussing this, are welcome.

Arthur

-- 
------------------------------------------------------------------------------
Arpanet: ARK@SALLY.UTEXAS.EDU
UUCP:    {gatech,harvard,ihnp4,pyramid,siesmo}!ut-sally!ark

nagler@ORB.UUCP (Rob Nagler) (02/28/86)

Hi Arthur.  How's the weather in TX?  Back to the discussion...

I guess what I should have said is that strong type checking is
subverted by the introduction of overloading.  I kind like the
idea of using the name of my procedure as acheck unto itself.
When you combine generics and overloading you lose the extra compile 
time type checking that you get with unique names for every 
procedure.  I realize that you can strongly type check anything,
but my main use for type checking is to catch errors at compile time
before integration.  

Rob

wyant@APOLLO.UUCP (Geoffrey Wyant) (03/03/86)

I would like to reply to Mr. Keller's comments on overloading:

I'm going to agree w/ Rob Nagler on this one, even though I think 
his example was poorly chosen. 

  ...........

> With overloading, controlled generic capability can be achieved. 
> Why would anyone want that? Well, would you want to have to distinguish
> between + for integer and + for reals?  Would you want to have to 
> invent unique names for each procedure that did an equivalent thing
> to its data type?

This is just the problem with overloading.  It provides a superficial
veneer of polymorphism over what are essentially different procedures.
If 2 procedures do the same thing and only differ in the data types
they take, why should I have 2 invent 2 different procedures ?  True
polymorphism would allow you to write only a single procedure.  If the
2 operations differ subtley (or even not so subtley) in their semantics,
I would claim that it is poor software engineering to allow them to
be named the same thing.

> I see nothing wrong with Mr. Nagler's example.  In fact, I like it
> because I wouldn't want to have to remember to use (say) PUT-ARRAY
> instead of PUT.

Again this instance, the PUT procedure shouldn't be overloaded, but
should be able to accept parameters of any type, provided said parameter
provides a "write" operation.

> If done at compile-time, you can use compile-time expansion as if the
> generic package were a macro with macro conditionals.  In some sense,
> overloading without generics can be thought of as a limited collection
> of macro expansions of the generic that used macro conditionals.

Macro expansion of types is the wrong way to think about type parameters.
It fails to allow for recursive types among other things.

Well, not that any of this has anything to do with Modula-2, and I'm
not proposing that M2 should be made polymorphic.  I just believe that
overloading is a knee-jerk approach to polymorhism, and the semantic
underpinnings fail to generalize in any sort of usefull fashion.

----------------------------


                                       Geoff Wyant
-------