[net.lang] Whats wrong with strong typing

leichter@yale-com.UUCP (Jerry Leichter) (12/13/83)

Strong typing as it is implemented has a couple of problems:

a)  It's an incomplete facility.  Giving a variable a compiler-checked type
is essentially an assertion about the values that variable will contain.
Originally, in the grand-daddy of all typed languages (FORTRAN), the assertion
was based on hardware limitations:  I promise to put nothing but integers in
this here variable, but I may put real numbers in that there variable.  Some
additional things got dragged along:  The definition of division was different
for different "types".

Well, it's rarely of great interest to me that a variable is always an
integer.  PASCAL took a great leap forward in adding some typing information
(ranges) that had not DIRECT correlation with hardware representation.
In the process, however, it lost the ability to provide complete checks at
compile time, and few PASCAL compilers check at run-time either.

However, the original basis of type distinctions remains in PASCAL and many
related languages:  The compiler provides a small, essentially arbitrary
set of assertions that it recognizes.  Consider that, for a two's-complement
machine, I can assert that the TOP bit is 0 (by an range assertion I >= 0),
but not that the BOTTOM bit is 0 (I is even - something that might be very
nice to be able to say if I is going to be used as a word address on an 11.)

b)  It requires me to tell the system things that it ought to be able to
figure out for itself.  If I is used ONLY as a loop counter, the compiler
can easily tell that I can only take on integer values.  Why should I have
to say so?  Let the compiler tell ME what it has decided it knows about
each of the variables.  In particular, let it tell me when it is unable to
learn enough about a variable to generate good code (it can always insert
run-time checks); then I can come back and provide such information as I
have.

People object to this approach on two grounds.   The first is a religeous
belief that "default declarations" are bad, because PL/I used them and we
all know that NOTHING that PL/I did was right.  The second is the belief that
the source code of a program tell a human reader everything about it.  I see
no requirement for this at all.  Let people read compiler listings, which the
compiler will then carefully annotate with the "missing" information.  With
proper design, the annotated compiler output could be use as INPUT to a later
compilation; you would just discard the original source and replace it with
the improved version.  We already do this with pretty-printers for the sake
of simple syntactic clean-up; there is no reason not to do it for "semantic
cleanup".

Finally, my own personal experience, in about 16 years of programming, both
in academia and industry, including a large amount of teaching of programming
and grading student programs, in a large variety of languages, is that the\
"problem" being solved by most strong-typing systems - compile-time checking
for inconsistencies - is just NOT a significant problem in real life.  in
my own code, I can think of ONE case where a type-confusion caused in problem
(in SNOBOL, and in a context that could not even be expressed in a language
without dynamic typing).  Problems I do find are more subtle and often have
to do with order and meaning of arguments to functions that take many argu-
ments - but usually there are multiple arguments of the same type so a
typing system wouldn't catch them anyway.  A more general assertional system
MIGHT - and would be an extraordinarily useful thing anyway, much more
useful than any static typing system I've ever seen.

Consider the interesting question of whether recursive functions should be
declared "recursive".  At one time, there were arguments for this:  After
all, a function that is NOT recursive can be executed more efficiently on
many architectures (especially old ones) since it can use a static context
frame.  Besides, on general "strong typing" arguments, I should be warning
the reader - and the compiler - about an important fact about my function.

"Recursive" declarations have pretty much disappeared.  Hardware stack support
was a contributer, but there was also the theoretical argument - which I
believe I once saw made by Dijkstra - that if a recursive declaration were to
be allowed, it should be checked.   But the only way to check if that a function
is or is not recursive is to compute the transitive closure of the call graph -
easy in "standard" PASCAL, with not external functions, for example - from
which one could as easily have the compiler decide for itself that the function
is or is not recursive.  Hence, the declaration is redundant.  My claim is
that the same reasoning ought to be applied to other type information.

							-- Jerry
					decvax!yale-comix!leichter leichter@yale

stevev@tekchips.UUCP (Steve Vegdahl) (12/14/83)

>>It's an incomplete facility ... [providing] a small, essentially arbitrary
>>set of assertions that it recognizes.  Consider that, for a two's-complement
>>machine, I can assert that the TOP bit is 0 (by an range assertion I >= 0),
>>but not that the BOTTOM bit is 0 (I is even - something that might be very
>>nice to be able to say if I is going to be used as a word address on an 11.)
>> ...
>>A more general assertional system MIGHT - and would be an extraordinarily
>>useful thing anyway, much more useful than any static typing system I've
>>ever seen.

This is not an argument against strong typing, but rather about the inadequacy
of implementations of strong typing.  Could Pascal not be extended so that
types could include assertions about evenness/oddness, to use your example?
Increasing the robustness of a strong typing mechanism seems like a fine idea.

>>It requires me to tell the system things that it ought to be able to
>>figure out for itself.  If I is used ONLY as a loop counter, the compiler
>>can easily tell that I can only take on integer values.  Why should I have
>>to say so?
>> ...
>>the "problem" being solved by most strong-typing systems - compile-time
>>checking for inconsistencies - is just NOT a significant problem in real
>>life.
>> ...
>>Hence, the declaration is redundant.  My claim is that the same reasoning
>>ought to be applied to other type information.

In my programming experience, such checks have aided me in catching a large
number of stupid bugs.  Having the compiler force you to make such
declarations may slightly increase your work, but once you're used to it,
and if you have a reasonable programming environment and language, the amount
of such work is insignificant.  I would suggest that features in a language
that increase the likelihood of checkable assertions in a the source code are
a good thing.  A strong typing mechanism certainly falls into this category.

>>religeous [sic] belief that "default declarations" are bad, because PL/I
>>used them and we all know that NOTHING that PL/I did was right.

I will elide the question of whether PL/I did ANYTHING right, but it is the
consensus of the computer scientists that I know that default declarations
are bad.  I done enough FORTRAN programming in my earlier days to know the
grief one can go through because of a variable that is automatically declared
because of a typo.

			Steve Vegdahl
			Tektronix, Inc.
			Beaverton, Oregon

davies@uiuccsb.UUCP (12/16/83)

#R:yale-com:-258200:uiuccsb:8900001:000:1107
uiuccsb!davies    Dec 15 18:08:00 1983

If you don't believe that automatic typing of variables doesn't cause errors,
then you must not have written any large Fortran programs.  The first thing
I look for when a program is behaving strangely is whether I forgot to declare
a variable, and it defaulted to the wrong type.  Some Fortran 77 compilers
(including Unix F77) have IMPLICIT UNDEFINED which requires explicit typing
of all variables.  I consider this to be quite a useful feature, which was
unfortunately left out of the ANSI 77 standard.

The company I work for has implemented a compiler that uses the suggestion
of sending the listing produced by the compiler back in as input.  Error and
other messages are marked in a way that causes the compiler to ignore them
the next time.  This allows editing of the listing to correct syntax errors,
which is very convenient.
By the way, we also have the options RECURSE and NORECURSE for procedures etc.
NORECURSE produces more efficient code in some cases.  This may seem an archaic
feature, but we are using this language to implement a large program and have
added it for practical reasons.

wls@astrovax.UUCP (William L. Sebok) (12/17/83)

One of the most common causes of errors in my C number crunching programs is
forgetting to declare floating point functions to be floating point. It is
easy to forget the integer default.
-- 
Bill Sebok			Princeton University, Astrophysics
{allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls

ucbesvax.turner@ucbcad.UUCP (12/24/83)

#R:yale-com:-258200:ucbesvax:4500006:000:2535
ucbesvax!turner    Dec 15 15:51:00 1983

/***** ucbesvax:net.lang / yale-com!leichter /  6:17 am  Dec 14, 1983*/
								...that the
    "problem" being solved by most strong-typing systems - compile-time checking
    for inconsistencies - is just NOT a significant problem in real life.
			   ...Problems I do find are more subtle and often have
    to do with order and meaning of arguments to functions that take many argu-
    ments - but usually there are multiple arguments of the same type so a
    typing system wouldn't catch them anyway.

How ironic--just 1/2-hour ago I fixed a bug of this kind.  The function took
four arguments, only two of which were integers.  In pascal (I'm writing in
C), they would have been "var integer".  The formal parameter names were
"ncols" and "nrows"--in that order.  The user of this routine confused the
order (quite naturally--most of us prefer to say "rows and columns" to
"columns and rows"), which blew up his code.  If C had better strong typing,
I would have solved this by having types "rowval" and "colval".  As it is,
we limp along, being quite poor programmers by Jerry's definition.  We do
terrible things like forget argument-order even for functions with small
numbers of arguments.

I am currently in the position of helping to support some channel-routing
code.  It has about 40 integer-type variables global to the whole routine.
Most of these are indices to very specific arrays.  The author didn't
type them as being specific subranges.  We wish that he had.  The algorithm
is published, and easily understood, but the code is a mess.  Strong typing
would have helped both in terms of maintenance and in making the code more
self-documenting.

(No, I don't claim that strong-typing makes programmers better.  But I do
believe that better programmers employ it, because they know better than
to believe for a minute in their own perfection.)

Re: declaration of functions as recursive

This is irrelevant to the discussion of the relative merits of strong typing.
When is such a distinction important for the kinds of uses to which strong
typing is put?  "recursive foo()" is a COMPILER-directive, implying that
recursiveness is a consideration in producing code that is faster or correctly
implemented.  It would never be a consideration in a statement like

	<fn ref 1> := <fn ref 2>

where one would certainly want to know that fn2 returned something of a type
castable to the return-type of fn1.  Jerry is making an argument by analogy,
the analogy does not exist.
---
Michael Turner (ucbvax!ucbesvax.turner)