Re: Static vs. Dynamic typing (big advantage or not)---WAS: c.programming: OOP and memory management

From: Cristiano Sadun (cristianoTAKEsadun_at_THIShotmailOUT.com)
Date: 07/12/04


Date: 12 Jul 2004 08:20:44 GMT

Steven T Abell <newsgroup@brising.com> wrote in news:MkyHc.19$yN1.4
@newsread1.mlpsca01.us.to.verio.net:

> Debugging a Java program
> involves dealing first with type errors,
> many of which are created by the fact that types are required,

I've heard this many times, but what exactly are these? Could you do some
meaningful examples?

And, from what you say it seems you're advocating no types at all - not
dynamic types only. So, what is it: given, say, an assignment, should the
runtime of the language attempt to convert the rvalue to something
compatible with the lvalue? Or verify whether or not the assignment is
properly overloaded with the type of the rvalue?

Let's have a look at some details: the prototype of error intercepted by
compile-time type enforcement is

int a = "hello";

or

String a = 1;

>From the current discussion it seems to me that a dynamically typed
language would:

 1) ignore or at most emit a warning in both cases;
 2) fail at runtime when executing the first statement, since there's no
   overload the assignment operator of "int" with a string parameter;
   (or attempt to interpret the string as a number?)
 3) not fail at runtime when executing the second statement,
   since it finds out that the assignment operator for String
   is overloaded with a number parameter

A warning in 1) is pointless: if the programmer knows what he's doing,
he's done the assignment on purpose; if he doesn't, than static typing
would serve him better.

For 2) and 3) we're swapping two error-checks at compile time (or,
probably:
  - the effort of thinking of the type system when writing and apply a
conversion;
  - and, therefore of thinking explicitly of the cases when the
conversion might fail;
  - so probably writing some code to check that the string is, actually,
denoting a number before attempting to convert) with one error at
runtime.

Now, what would a dynamically typed language should do for

int a = "1"

?

Is this still a (runtime) error? Is a type conversion automatically
attempted?

If it's an error, then the saving is only apparent: you *still* have to
go correct the code so that a conversion is in place, and probably a pre-
check to see wether such conversion is feasible.

If a conversion is automatically attempted, the only way *not* to have
runtime errors is to know that, when the line is executed, the string in
the rvalue is actually denotig a number (and is not "hello").

Otherwise, you just find out about the error later in the process, *and
only when testing with certain input sequences*. Your program could go on
for days working perfectly and suddendly boom - something we don't want.

Since we're talking programs, "know" can only mean that there's a code
invariant for which that rvalue is always denoting a number, and that
invariant must, somewhere, be explicitly checked (to protect from faulty
input) (note that the need of this check is, due to the situation, less
pressant, and more easily delayed - and perhaps forgotten until runtime
error occurs - in any programming situation slightly less than ideal).

The only case when such invariant doesn't need checking is when it
descends from the other invariants and the code (that is, when, for
example, the string is computed internally and thus further checks are
redundant and unnecessary).

Even assuming the programmer's logical and combinatorial abilities are
infallible (mine aren't), it still turns out that the only situation
where there's a real gain is when:

 - the language attempts conversions automatically
 - the variables/method calls you're dealing with have type properties
which are independent from the program input, in the sense that can be
completely inferred by the previous computation and the simple fact that
the computation has reached them without failing. To make an example in:

 Object obj = ...
 if (obj instanceof Bear) {
    ((Bear)obj).growl();
 }

the programmer knows that within the if.. branch the type of obj is
"Bear", but most compilers wouldn't (and thus a cast has to be written in
a statically type-checked language).

This seems to me a quite small percentage of the cases. In all other
casess, static check is equivalent to dynamic check, and actually
prevents errors - forcing, yes, the programmer to put explicit effort in
thinking clearly and, ultimately, doing is job. Doesn't seem so bad to
me.

Finally, what if more than one conversion is possible? How to
disambiguate? C has long taught us that implict conversions lead to
faulty code - and faulty in subtle ways, hard to understand and trace.

> and then gets down to runtime problems.

I suspect that a lot would depend from the programmer's approach and
style: I seldom do blatant type errors (as I did when I started coding ;)
since I constantly think of the type system. Maybe if a programmer see
the type system as an impediment, it tends to ignore it when coding -
resulting in type errors?

Actually, to me, it gets down to write tests for suspicious cases where I
know the boundaries of my code are touched.