[comp.lang.misc] Run-time Type Errors in Smalltalk

mario@cs.man.ac.uk (Mario Wolczko) (04/05/91)

In article <887@puck.mrcu>, paj@mrcu (Paul Johnson) writes:
> Sorry, I am still not convinced.  I am currently programming in
> Eiffel, and changing my mind about a type is not something I often do.
> Also the type declarations carry information which affects the
> execution of the rest of the program.  Hence other parts of the
> program will need changing as well.  It seems to me that this will
> only result from a fairly major rewrite of some part of the code.

This could be a self-fulfilling statement, ie you don't change your
mind about types because you know it's going to be hard work to fix
the type declarations up, whereas in a declarationless language
sorting out the declarations doesn't arise.

> Does anyone have any facts relating to the assertion that run-time
> failures due to type errors are rare in Smalltalk development?

I'm not sure what this means in Smalltalk, much less how you measure
it.  You can't just count "doesNotUnderstands", because some of these
are not type errors (such as asking for the tail of an empty list).

As for statistics, do you want "how many Smalltalk programs have ever
given a run-time type error in their whole lifetime, after they were
declared to be `finished'?"  Most Smalltalk programs I have seen are
prototypes or research programs, and are rarely declared "finished",
so I guess this would be close to 100%.  However, if you ask this
question of any language, replacing "type error" with "error", then my
guess is that the answer is the same.  Very few "finished" programs
are bug-free, type-checked or not, so it's clear that type checking is
only addressing a small part of the problem.

Or perhaps you mean "how many runs of Smalltalk programs have resulted in
run-time type errors?".  This must be close to 0%.  Neither of these
figures means very much.  

Speaking from personal experience, I find that after I have written
some Smalltalk code (and I have written >10000 lines in the last 18
months) there are a few residual "type errors" which get caught in the
first few test runs.  The time taken to find and fix these is much
smaller than the time it would take me to declare all the variables in
such a way as to satisfy a type-checker (even if it were possible with
current type systems, which it isn't in many programs).

The real problems that take hours to find and fix are undetectable
using type-checking, such as writing "x+y" instead of "x-y".

Mario Wolczko

   ______      Dept. of Computer Science   Internet:      mario@cs.man.ac.uk
 /~      ~\    The University              uucp:      mcsun!ukc!man.cs!mario
(    __    )   Manchester M13 9PL          JANET:         mario@uk.ac.man.cs
 `-':  :`-'    U.K.                        Tel: +44-61-275 6146  (FAX: 6280)
____;  ;_____________the mushroom project___________________________________

cok@islsun.Kodak.COM (David Cok) (04/05/91)

In article <2367@m1.cs.man.ac.uk> mario@cs.man.ac.uk (Mario Wolczko) writes:
>In article <887@puck.mrcu>, paj@mrcu (Paul Johnson) writes:
>> Sorry, I am still not convinced.  I am currently programming in
>> Eiffel, and changing my mind about a type is not something I often do.
>> Also the type declarations carry information which affects the
>> execution of the rest of the program.  Hence other parts of the
>> program will need changing as well.  It seems to me that this will
>> only result from a fairly major rewrite of some part of the code.
>
>This could be a self-fulfilling statement, ie you don't change your
>mind about types because you know it's going to be hard work to fix
>the type declarations up, whereas in a declarationless language
>sorting out the declarations doesn't arise.

I've never known a case where one had to go through a program and fix up all
the types.  In Fortran or Pascal one might have to, but in C, use descriptive
typedef names -- then all one needs to do to change the types of those 
variables is to change the definition of the typedef.  This is very like 
changing the class definition in any dynamically typed language.

Historical note:
I vaguely remember from some early programming class ages ago that declarations
were touted not as a way to provide type-checking, but to save the
programmer from misspelling variable names (by requiring that each one be
written at least twice in a program)! FORTRAN's implicit declarations
were forbidden in that class.

David R. Cok
Eastman Kodak Company -- Imaging Science Lab
cok@Kodak.COM

new@ee.udel.edu (Darren New) (04/06/91)

In article <1991Apr5.152736.22353@kodak.kodak.com> cok@islsun.Kodak.COM (David Cok) writes:
>I vaguely remember from some early programming class ages ago that declarations
>were touted not as a way to provide type-checking, but to save the
>programmer from misspelling variable names (by requiring that each one be
>written at least twice in a program)! 

This does not preclude dynamic typing.  In Smalltalk, you declare the
names of all your local variables. The first time you compile code with
a new global variable, it confirms that you spelled it right and allows
you to find the "closest fit" name if not (try *that* in your favorite C compiler :-).  Dynamic typing just means that declarations don't include types,
not that they don't declare variables.

>FORTRAN's implicit declarations
>were forbidden in that class.

And how did you know that you didn't implicitly declare a variable
by mistake?   (or do you mean FORTRAN's implicit *statement*?)
	    -- Darren

-- 
--- Darren New --- Grad Student --- CIS --- Univ. of Delaware ---
----- Network Protocols, Graphics, Programming Languages, FDTs -----
  +=+=+ My time is very valuable, but unfortunately only to me +=+=+
+ When you drive screws with a hammer, screwdrivers are unrecognisable +

olson@lear.juliet.ll.mit.edu ( Steve Olson) (04/07/91)

In article <887@puck.mrcu> paj@mrcu (Paul Johnson) writes:
   Does anyone have any facts relating to the assertion that run-time
   failures due to type errors are rare in Smalltalk development?

For years I have been using an object-oriented Lisp (Flavors) to do
things like real-time interpretation of weather radar imagery.  For
the purpose of this discussion Lisp plus Flavors is probably equivalent
to Smalltalk.  These systems have been deployed at several radar sites
scattered across the country for several years.  My only possible reply
is "huh, whats a type error?"  Oh yes! I remember now - a type error is
what happens when you are programming in C and you screw up a cast.  

Seriously, I get the "message not understood" error from time to time, but
99 times out of a hundred, the problem is caught on the first or second
test run.  The other 1 out of hundred?  Well, I still get to diagnose and
fix the problem almost instantly because of the usually informative error
messages.  Much better than the mystery core dump.  I get things which look
like type errors when try to perform math on 'nil' for example, but thats
almost always because I have forgotten to properly calculate the value
of some slot.  Getting a type error in those cases is in fact a tremendous
help over what would happen in a typical statically typed language.

In my opinion, the biggest practical problem with dynamically typed languages
is that it is a pain in the butt to lug around the run time envirnoment.
To run a 1 page Common Lisp program on a UNIX system means I have to fire up a
multi-megabyte run time system which consumes vast amounts of core and virtual
memory.  Yuk.  There are lighter-weight alternatives to Common Lisp, of course,
but you're still going to have some extra baggage to lug around.

People who get endlessly alarmed about the alleged lack of type saftey in
a dynamically-typed languge are not well-informed about how Lisp or Smalltalk
software development actually works.

- Steve Olson
  MIT Lincoln Laboratory
  olson@juliet.ll.mit.edu

diamond@jit345.swstokyo.dec.com (Norman Diamond) (04/08/91)

In article <OLSON.91Apr6172626@lear.juliet.ll.mit.edu> olson@lear.juliet.ll.mit.edu ( Steve Olson) writes:

>In my opinion, the biggest practical problem with dynamically typed languages
>is that it is a pain in the butt to lug around the run time envirnoment.
>To run a 1 page Common Lisp program on a UNIX system means I have to fire up a
>multi-megabyte run time system which consumes vast amounts of core and virtual
>memory.  Yuk.

Exactly.  The multi-megabyte run time system provides the "message not
understood" message and nice debugger instead of mystery core dump.
The multi-megabyte run time system would be useful while developing
programs in statically typed languages too, and then you'd never see
the mystery core dump.  Debates between static and dynamic typing should
center on the advantages of programming in each kind of language, not
on what can be done with multi-megabyte support packages.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

new@ee.udel.edu (Darren New) (04/09/91)

In article <OLSON.91Apr6172626@lear.juliet.ll.mit.edu> olson@lear.juliet.ll.mit.edu ( Steve Olson) writes:
>People who get endlessly alarmed about the alleged lack of type saftey in
>a dynamically-typed languge are not well-informed about how Lisp or Smalltalk
>software development actually works.

Here, Here!  I'll second that.  And people who say "Well, you could do it 
just as well in a statically typed language if you had as big a runtime
system" I'll answer by saying "why do *most* dynamic languages have huge
libraries and great debuggers and *most* static languages have lousy
libraries and lousy debuggers?"  I suspect that because the static code
is so much less reusable that the incentive is to never change the
late-60's model of programming lest we break all that software.
People rave about GDB, but it looks worse to me than Delta on a
1968 release of CP-V.  Then look at the Smalltalk debugger, which
is not very big because it resuses most of the code from the editor,
browser, and compiler, and it blows any other debugger out of the water.
	       -- Darren

-- 
--- Darren New --- Grad Student --- CIS --- Univ. of Delaware ---
----- Network Protocols, Graphics, Programming Languages, FDTs -----
  +=+=+ My time is very valuable, but unfortunately only to me +=+=+
+ When you drive screws with a hammer, screwdrivers are unrecognisable +

guido@cwi.nl (Guido van Rossum) (04/09/91)

Norman Diamond writes:

>The multi-megabyte run time system would be useful while developing
>programs in statically typed languages too, and then you'd never see
>the mystery core dump.  Debates between static and dynamic typing should
>center on the advantages of programming in each kind of language, not
>on what can be done with multi-megabyte support packages.

Maybe I can provide something of a data point here: a comparison of
two languages that differ more in their typing system than in other
aspects.  If you know ABC and Python you can skip to DISCUSSION at the end.

Python, which has dynamic typing, was strongly inspired by ABC, which has
static typing.  In other aspects, the two are much more similar then
your average pair of statically/dynamically typed languages: both are
interactive and interpreted, and have large runtime packages that
replace core dumps by understandable error messages (really exceptions
for Python).  Both runtime packages implement very-high level data
types with roughly the same functionality (only one has bignums --
oddly enough it's the statically typed one).  Neither requires or
allows declarations, both have polymorphic functions.

And now the differences: the type system of ABC determines the type of
parameters and variables by inspecting how they are used -- e.g., if
it is added to something, it must be a number (there's only one
numeric type in ABC), if it is inserted in a list, it must have the
same type as the elements of that list, etc.  You get polymorphism if
the usage of a parameter doesn't give away all the information about a
type -- e.g., if a procedure swaps its two arguments but does nothing
else, it will accept arguments of any type, as long as the two
arguments have the same type.  There are interesting problems when you
try to write a type-checker for such a language, but they are solvable
(for ABC, at least).

Python, on the other hand, does all its type checking at run time.
E.g., if you try to add two objects, their types are compared, and if
they are both strings, or both integers, it succeeds, else you get a
type checking exception (which may be caught).

Programming in either language is extremely smooth compared to C or
other relatively low-level languages.  Because of the interpreters,
you don't get blinding speed if you can't get the built-in data types
to do most of the work for you, so neither language (implementation)
is well-suited for programming byte-copying loops or FFT transforms,
for example; but if you need efficient, large dynamic data structures,
they are available in the runtime system.

DISCUSSION

There are two questions which can be asked about ABC and Python (in
the context of the previous debate about static vs. dynamic typing).

1) Which is more likely to lead to bugfree programs?
2) Which has more flexibility (or: which do you like better)?

Re (1), I don't see a significant difference.  True, ABC detects
certain errors before you start running the program that Python will
only catch in a test run, but there remains a significant class of
errors that can only be detected at run time, e.g., taking the MIN of
an empty list, accessing an associative array with a non-existent key,
etc.  Both Python and ABC encourage program development in small units
that are created and tested bottom-up, and the first test run usually
finds any type errors that remain in Python programs.  Sometimes the
type checker in ABC detects a type error but reports it in such a
weird way that you have to stare really long at the piece of code in
question before you see what the real problem is; e.g., it may
complain that b is not a number in a+b, while the real problem is in
the expression assigned to b many lines earlier.  In Python I can ask
the debugger to print b's value when an exception has occurred, which
usually shows immediately what the problem is (the value gives a more
precise clue about where it came from than just the type, which ABC
reports).

Re (2), it can't be a surprise that I like Python better.  I actually
use heterogeneous lists a lot, e.g., just this weekend I wrote a
tree module which stores arbitrary attributes associated with the
leaves, keyed on strings chosen by the various modules that use the
trees, and an event queue which can store arbitrary events from
unrelated modules.  These modules would pass ABC's type system
alright (except for other features not provided in ABC that don't
relate directly to dynamic/static typing), but their callers wouldn't:
as soon as two unrelated modules would store differently-typed events
in a queue, neither module would type-check.  This is caused by the
absence of unions in ABC, but notice that they would have to be
open-ended unions (David Gudeman's "any" type), since the queue module
cannot know what types will be stored in the queue.  Any one program
will only store a finite number of different event types (hmm, can you
prove this?) but I don't see the point of forcing the programmer to
find out which union type to use in a particular program (and keeping
it up-to-date when the program is extended).

CONCLUSION

Were all else kept equal, I'd still prefer dynamic typing.  Its
simplicity in implementation wins over the complexity of a type
checker that provides the kind of flexibility I need.  ABC is close,
but still too limiting for many realistic applications, and its type
checker was one of the hardest modules to add to the system.

Note that dynamically typed languages can often be optimized using
techniques similar to ABC's type checking algorithm -- only they can
fall back on the dynamic type system if they can't compute the
type of a variable, instead of blaming the user.  I would even like it
if such an optimizer told me when it could prove that an unchecked
exception would certainly occur in a part of the program.  But there
is no reason why such an optimizer should stop at type checking --
static checks can check for definedness of variables (ABC has this!),
apply range checks, in short try to predict every kind of exception
that may occur in a program -- but there is no reason to restrict the
language to accept only programs for which it can be proven (with
known techniques) that no exception will ever occur.  Such languages
are unnecessarily restricting programmers.

--Guido van Rossum, CWI, Amsterdam <guido@cwi.nl>
"I can do everything you want in Macro Assembler.  No need for Compilers."

olson@lear.juliet.ll.mit.edu ( Steve Olson) (04/09/91)

In article <1991Apr8.085602.5082@tkou02.enet.dec.com> diamond@jit345.swstokyo.dec.com (Norman Diamond) writes:
   The multi-megabyte run time system would be useful while developing
   programs in statically typed languages too, and then you'd never see
   the mystery core dump.  

I certainly agree with the first part of your statement - witness Saber-C -
but not the second.  The real gut-buster problems I see in my line of work
are when a guy calls up from a remote site and says "It ran great for 3 days,
and then it crashed!!".  My experience has been that the dynamically-typed
system fails and you fix it the first time.  When the statically typed
system fails ... maybe you get lucky ... maybe you don't.  Note:  I'm
assuming the statically typed system is "deployed" without the run-time
environment - see below.

                            Debates between static and dynamic typing should
   center on the advantages of programming in each kind of language, not
   on what can be done with multi-megabyte support packages.

Agreed in principle, but harder to do than you think.  The poster who
talked about "A" and "B" languages accurately described how languages
- in practice - tend to line up.  Dynamic typing pretty much implies a
elaborate run-time environment, so to do an "apples-to-apples" comparison
we need a statically-typed language with a elaborate run-time enviroment.
So go off and design one, and report back to this list :-).  Or maybe some 
exist - enlighten me.

   --
   Norman Diamond       diamond@tkov50.enet.dec.com
   If this were the company's opinion, I wouldn't be allowed to post it.

- Steve Olson
  MIT Lincoln Laboratory
  olson@juliet.ll.mit.edu

diamond@jit345.swstokyo.dec.com (Norman Diamond) (04/09/91)

In article <3288@charon.cwi.nl> guido@cwi.nl (Guido van Rossum) writes:

>Python, which has dynamic typing, was strongly inspired by ABC, which has
>static typing.  In other aspects, the two are much more similar then
>your average pair of statically/dynamically typed languages: both are
>interactive and interpreted, and have large runtime packages that
>replace core dumps by understandable error messages (really exceptions
>for Python).
[...]
>Were all else kept equal, I'd still prefer dynamic typing.

Dynamic typing indeed makes some things easier, as Mr. Rossum explained.
It is nice to see real evidence for a change.

Anyway, there is a middle ground which has also been suggested by a few
others, and which some languages (e.g. Eiffel, and certain constructs in
C++) come close to providing anyway.  Perhaps some new terms would help
explain this.  Just as type and class have come to mean different things,
perhaps dynamic classing vs. static classing should be recognized.  With
static classing, a type inference system could determine, or a programmer
could specify, that a variable inherits certain known messages, though the
precise type need not be known statically.  I expect that static classing
will have a lot more use than static typing.

I would not try to ram either static typing or static classing down
anyone's throat, but both can be used by disciplined developers and
maintainers to catch some errors early.  Although it cannot catch all
errors, it certainly helps.  Part of the folklore of software engineering
is the magnitude of increase in costs as error detection is delayed.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

adw@otter.hpl.hp.com (Dave Wells) (04/11/91)

olson@lear.juliet.ll.mit.edu ( Steve Olson) writes:
>People who get endlessly alarmed about the alleged lack of type saftey in
>a dynamically-typed languge are not well-informed about how Lisp or Smalltalk
>software development actually works.

Disclaimer: there almost certainly are people who *are* overly concerned
with runtime type safety in dynamically-typed languges, and who needlessly
lie awake at night worrying about it.

However. There have also been claims that "type errors are actually quite
rare in dynamically-typed languges". (Anecdotal evidence follows). We have
just developed an 18k LOC, 83 user-class application using ACTOR (SmallTalk
72 with sugared syntax for the PC). We found that a majority of the bugs
would have been caught by even a simple (i.e. 'ANSI-C-like') static
typechecker.

Although most of these (those which we've found so far :-|) were found "on
the first pass through", testing such a relatively large interactive
application exhaustively *and repeatedly* is exceedingly expensive compared
to a comparable compilation-style typecheck.

You may also be interested by the following definition of "=" for Sets,
adapted from the ACTOR kernel source. Can you spot the type error? Can you
explain why it means that testing for membership in a heterogeneous Set
containing both Sets and Strings (say) *sometimes* fails with a runtime
type error (depending on how the Set members hash into physical locations
in the Set)?

/* Infix equality method for Sets. Sets are equal if they are the same size
and have equal members. */
Def =(self, collection)
{ if size(self) ~= size(collection)
  then ^nil
  endif;
  do(self,{using(member)
    if not(member in collection)
    then ^nil
    endif;
  });
}!!

I'd be happy with manifest types with static checking, even if it were
optional. I'd be happy with a type inference system which would tell me
that "<collection> must understand size() and in(). This makes it an Array,
Bag, Set or Interval." But, for the kind of development work we're doing,
I'm not at all happy with neither.

diamond@jit345.swstokyo.dec.com  Norman Diamond at Digital Equipment
Corporation Japan writes:
|Anyway, there is a middle ground ... [details omitted] ...
|
|I would not try to ram either static typing or static classing down
|anyone's throat, but both can be used by disciplined developers and
|maintainers to catch some errors early.  Although it cannot catch all
|errors, it certainly helps.  Part of the folklore of software engineering
|is the magnitude of increase in costs as error detection is delayed.

Exactly.

Dave

klimas@iccgcc.decnet.ab.com (04/13/91)

In article <OLSON.91Apr6172626@lear.juliet.ll.mit.edu>, olson@lear.juliet.ll.mit.edu ( Steve Olson) writes:
> In article <887@puck.mrcu> paj@mrcu (Paul Johnson) writes:
>    Does anyone have any facts relating to the assertion that run-time
>    failures due to type errors are rare in Smalltalk development?
	Some info that I picked up from a company doing a lot of big
	project work with C++ (i.e. strong type checking language) was
	that postmortems on their project revealed only 10% of their
	errors were captured by strong type checking.

rsw@cs.brown.EDU (Bob Weiner) (04/13/91)

In article <4243.2805b94a@iccgcc.decnet.ab.com> klimas@iccgcc.decnet.ab.com writes:
> 	Some info that I picked up from a company doing a lot of big
> 	project work with C++ (i.e. strong type checking language) was
> 	that postmortems on their project revealed only 10% of their
> 	errors were captured by strong type checking.

I doubt that any professional software designers are willing to log every
instance that their compiler spits out an error.  Their productivity might
drop considerably.  Hence it is a fair bet that this company did not have
an accurate record of errors detected by a compiler for a strongly typed
language.  They may have only recorded problems found as the software
passed from design to quality testing.
--
Bob Weiner				   rsw@cs.brown.edu

cok@islsun.Kodak.COM (David Cok) (04/14/91)

In article <4243.2805b94a@iccgcc.decnet.ab.com> klimas@iccgcc.decnet.ab.com writes:
>	Some info that I picked up from a company doing a lot of big
>	project work with C++ (i.e. strong type checking language) was
>	that postmortems on their project revealed only 10% of their
>	errors were captured by strong type checking.

Did they really count ALL the errors -- including every time a compile failed
because of type errors?  It seems to me most type errors would be caught
before a peice of code even got into some error tracking process.

David R. Cok
Eastman Kodak Company
cok@Kodak.COM

ddean@rain.andrew.cmu.edu (Drew Dean) (04/14/91)

In article <4243.2805b94a@iccgcc.decnet.ab.com> klimas@iccgcc.decnet.ab.com writes:
>	Some info that I picked up from a company doing a lot of big
>	project work with C++ (i.e. strong type checking language) was
>	that postmortems on their project revealed only 10% of their
>	errors were captured by strong type checking.
I think this depends on what you call "strongly typed."  Personally, I wouldn't
call any C derived language strongly typed, as long as (void *) exists.
If you want to see REAL strong typing, try, say Standard ML (Ok, ok, it's
a functional language so I shouldn't be mentioning it in this group.  :-)
I don't want to start the functional vs OOP flamefest.)   I'm just using this
as an example of a really strong type system: wherever it can, it automatically
infers the type of the expression, and won't compile anything that doesn't
typecheck.
The only experience with dynamically-typed systems I have are Lisp-based
systems, just today I crashed one with a type error.  It could be that
imperative/functional programs are more prone to type-errors that OO programs;
(note: this is a conjecture) does anyone have any real data on the subject ?


-- 
Drew Dean
Drew_Dean@rain.andrew.cmu.edu
[CMU provides my net connection; they don't necessarily agree with me.]

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/14/91)

In article <RSW.91Apr13042119@delay.cs.brown.EDU> rsw@cs.brown.EDU (Bob Weiner) writes:
> In article <4243.2805b94a@iccgcc.decnet.ab.com> klimas@iccgcc.decnet.ab.com writes:
> > 	Some info that I picked up from a company doing a lot of big
> > 	project work with C++ (i.e. strong type checking language) was
> > 	that postmortems on their project revealed only 10% of their
> > 	errors were captured by strong type checking.
> I doubt that any professional software designers are willing to log every
> instance that their compiler spits out an error.  Their productivity might
> drop considerably.

It takes no effort to log every compilation. I do, and I know others who
do. It does take effort to log every little change you make to your
program, and every run-time error; I don't know of any C++PSE, though
the company might have developed one internally.

> Hence it is a fair bet that this company did not have
> an accurate record of errors detected by a compiler for a strongly typed
> language.

It's a fair bet that the 10% was fabricated by some programmer who at
the last minute was put on the spot and told to produce some statistics.
But I'd believe that it was in the ballpark: a language which forces you
to know what data types you're using will reduce type errors.

---Dan

diamond@jit345.swstokyo.dec.com (Norman Diamond) (04/15/91)

In article <4243.2805b94a@iccgcc.decnet.ab.com> klimas@iccgcc.decnet.ab.com writes:
>	Some info that I picked up from a company doing a lot of big
>	project work with C++ (i.e. strong type checking language) was
>	that postmortems on their project revealed only 10% of their
>	errors were captured by strong type checking.

This is a perfect example of engineering skills that have been learned
through hard efforts and then rejected by practitioners who refuse to
be engineers.

In any other field of engineering, a 10% increase in safety would always
be applied.  To reject it would be grounds for lawsuits, at least.

(Well, it did take a while before the auto industry accepted that lesson.
And one of the fallouts of the Reagan era is lower safety standards in
the auto industry.  Hmm.....)
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

gudeman@cs.arizona.edu (David Gudeman) (04/16/91)

In article  <1991Apr15.065146.16680@tkou02.enet.dec.com> Norman Diamond writes:
]In article <4243.2805b94a@iccgcc.decnet.ab.com> klimas@iccgcc.decnet.ab.com writes:
]>	Some info that I picked up from a company doing a lot of big
]>	project work with C++ (i.e. strong type checking language) was
]>	that postmortems on their project revealed only 10% of their
]>	errors were captured by strong type checking.
]...
]In any other field of engineering, a 10% increase in safety would always
]be applied.  To reject it would be grounds for lawsuits, at least.

How do you get a 10% increase in safety from the above?  If they
hadn't caught those errors by static typing they would have caught
them by testing -- the same way the found the other 90% of the errors.
This logic error combined with the strident tone of the article
suggests that your convictions are affecting your thinking.
--
					David Gudeman
gudeman@cs.arizona.edu
noao!arizona!gudeman

cs450a03@uc780.umd.edu (04/16/91)

Brian Boutel writes:

>The claim that testing catches all errors is laughable. Errors show
>up in production code every day. Testing, as we tell first year
>students, does not demonstrate the absence of errors, only their
>presence.

By the same token, the claim that static typing catches all errors is
invalid.  And if a language _requires_ a significant amount of
programmer time to be spent micro-managing static type declarations,
it introduces the possibility for more errors -- errors which may not
be caught in testing.

>So what can be said about all the errors in the quoted C++ project
>that were not caught by testing and are still in the production code?
> 
>I'll tell you. They are not type errors.

No, they were not _static_ type errors.  You don't know if they'd be
caught by run-time type checking.

Raul Rockwell

brian@comp.vuw.ac.nz (Brian Boutel) (04/16/91)

In article <1917@optima.cs.arizona.edu>, gudeman@cs.arizona.edu (David
Gudeman) writes:
|> In article  <1991Apr15.065146.16680@tkou02.enet.dec.com> Norman
|> Diamond writes:
|> ]In article <4243.2805b94a@iccgcc.decnet.ab.com>
|> klimas@iccgcc.decnet.ab.com writes:
|> ]>	Some info that I picked up from a company doing a lot of big
|> ]>	project work with C++ (i.e. strong type checking language) was
|> ]>	that postmortems on their project revealed only 10% of their
|> ]>	errors were captured by strong type checking.
|> ]...
|> ]In any other field of engineering, a 10% increase in safety would
|> always
|> ]be applied.  To reject it would be grounds for lawsuits, at least.
|> 
|> How do you get a 10% increase in safety from the above?  If they
|> hadn't caught those errors by static typing they would have caught
|> them by testing -- the same way the found the other 90% of the
|> errors.
|> This logic error combined with the strident tone of the article
|> suggests that your convictions are affecting your thinking.
|> --

The claim that testing catches all errors is laughable. Errors show up
in production code every day. Testing, as we tell first year students,
does not demonstrate the absence of errors, only their presence.

The figures quoted refer only to errors that have been detected, not to
all errors.

So what can be said about all the errors in the quoted C++ project that
were not caught by testing and are still in the production code? 

I'll tell you. They are not type errors.

--brian

 
-- 
Internet: brian@comp.vuw.ac.nz
Postal: Brian Boutel, Computer Science Dept, Victoria University of Wellington,
        PO Box 600, Wellington, New Zealand
Phone: +64 4 721000   Fax: +64 4 712070

sakkinen@jyu.fi (Markku Sakkinen) (04/16/91)

In article <1917@optima.cs.arizona.edu> gudeman@cs.arizona.edu (David Gudeman) writes:
>In article  <1991Apr15.065146.16680@tkou02.enet.dec.com> Norman Diamond writes:
>]In article <4243.2805b94a@iccgcc.decnet.ab.com> klimas@iccgcc.decnet.ab.com writes:
>]>	Some info that I picked up from a company doing a lot of big
>]>	project work with C++ (i.e. strong type checking language) was
>]>	that postmortems on their project revealed only 10% of their
>]>	errors were captured by strong type checking.
>]...
>]In any other field of engineering, a 10% increase in safety would always
>]be applied.  To reject it would be grounds for lawsuits, at least.
>
>How do you get a 10% increase in safety from the above?  If they
>hadn't caught those errors by static typing they would have caught
>them by testing -- the same way the found the other 90% of the errors.

It is very wishful thinking that all errors would be found by testing.
"Testing can only prove the presence of errors, never their absence."
But I think this quote is from Hoare, whom you probably would not
believe anyway.

>This logic error combined with the strident tone of the article
>suggests that your convictions are affecting your thinking.
>--
>					David Gudeman

Look who's talking!  When you have a difference of opinion with Diamond,
you call his opinion a "logic error" and then accuse him of "strident tone".
BTW, it would be a queer conviction indeed that wouldn't affect a person's
thinking at all.

Markku Sakkinen
Department of Computer Science and Information Systems
University of Jyvaskyla (a's with umlauts)
PL 35
SF-40351 Jyvaskyla (umlauts again)
Finland
          SAKKINEN@FINJYU.bitnet (alternative network address)

dnsurber@lescsse.jsc.nasa.gov (Douglas Surber) (04/16/91)

In <1917@optima.cs.arizona.edu> gudeman@cs.arizona.edu (David Gudeman) writes:

>If they
>hadn't caught those errors by static typing they would have caught
>them by testing -- the same way the found the other 90% of the errors.
>This logic error combined with the strident tone of the article
>suggests that your convictions are affecting your thinking.

The real question is how long would it take them to catch those errors
by testing?  The type checker catches them all first time every time.
Admittedly not every error, but reducing the number of errors by 10%
before you even begin testing sounds like a win to me.  

Further, the type checker finds type errors even in code that, for one
reason or another, is never excersized during testing.  Again not every
error, but a 10% reduction is still something.

--
Douglas Surber                 Internet: dnsurber@jsc.nasa.gov
Lockheed                       NASAmail: dnsurber/jsc/nasa
Houston, Texas                 Phone:    713-283-5195
Life can be only understood backwards, but it must be lived forwards.

mathew@mantis.co.uk (mathew) (04/16/91)

diamond@jit345.swstokyo.dec.com (Norman Diamond) writes:
> In article <4243.2805b94a@iccgcc.decnet.ab.com> klimas@iccgcc.decnet.ab.com w
> >	Some info that I picked up from a company doing a lot of big
> >	project work with C++ (i.e. strong type checking language) was
> >	that postmortems on their project revealed only 10% of their
> >	errors were captured by strong type checking.
[...]
> In any other field of engineering, a 10% increase in safety would always
> be applied.  To reject it would be grounds for lawsuits, at least.

Possibly true, although I can think of examples in other fields of
engineering where 10% increases in safety have NOT been applied. Look at the
design of roll-on, roll-off ferries, for example. Or US domestic electrical
wiring (no earth, no ELCB!)

Also, remember that using a strongly-typed statically typed language is not
necessarily the only way to achieve that 10% increase.


mathew

--
If you're a John Foxx fan, please mail me!

dmg@ssc-vax (David M Geary) (04/16/91)

In article <387@smds.UUCP>, Brian Boutel writes:

In article <1917@optima.cs.arizona.edu>, gudeman@cs.arizona.edu (David
Gudeman) writes:
|> In article  <1991Apr15.065146.16680@tkou02.enet.dec.com> Norman
|> Diamond writes:
|> ]In article <4243.2805b94a@iccgcc.decnet.ab.com>
|> klimas@iccgcc.decnet.ab.com writes:
|> ]>	Some info that I picked up from a company doing a lot of big
|> ]>	project work with C++ (i.e. strong type checking language) was
|> ]>	that postmortems on their project revealed only 10% of their
|> ]>	errors were captured by strong type checking.
|> ]...
|> ]In any other field of engineering, a 10% increase in safety would
|> always
|> ]be applied.  To reject it would be grounds for lawsuits, at least.
|> 
|> How do you get a 10% increase in safety from the above?  If they
|> hadn't caught those errors by static typing they would have caught
|> them by testing -- the same way the found the other 90% of the
|> errors.

]The claim that testing catches all errors is laughable. Errors show up
]in production code every day. Testing, as we tell first year students,
]does not demonstrate the absence of errors, only their presence.

] So what can be said about all the errors in the quoted C++ project that
] where not caught by testing and are still in the production code?

] I'll tell you. They are not type errors.

  Not neccessarily:  

struct junk  { int  x;  float  f; };
struct other { int  y;  double d; };

main() 
{
  static struct junk  myJunk = {1, 1.1};
  struct junk  *p = &myJunk;

  printf("%d\n", ((struct other*)myJunk)->x);
}

  Looks like a type error that got by the compiler to me.  Note that statically
typed languages (such as C++) usually contain some mechanism (here, the cast)
so that the typing system enforced by the compiler may be circumvented.
Therefore, as shown above, type errors can still get by the compiler.

  In fact, in C++, considerable effort is expended (via manipulating the
inheritance tree, or casting derived classes to base classes, etc) to ensure 
that the compiler will accept a given expression as "type safe".  However,
the given expression may well violate the type system.  Errors such as this
are difficult to track down ...

gudeman@cs.arizona.edu (David Gudeman) (04/17/91)

In article  <1991Apr15.234559.16293@comp.vuw.ac.nz> Brian Boutel writes:
]|> 
]|> How do you get a 10% increase in safety from the above?  If they
]|> hadn't caught those errors by static typing they would have caught
]|> them by testing -- the same way the found the other 90% of the
]|> errors.

]The claim that testing catches all errors is laughable.

Sure is.  Did someone make that claim?

]The figures quoted refer only to errors that have been detected, not to
]all errors.

And the errors that can be caught by static type checking are almost
universally so trivial that they probably all _would_ be caught by
testing.  The same cannot be said for the errors introduced by complex
code that is trying to get around the static type declarations -- to
do something that would be easy in a dynamically typed language.

]So what can be said about all the errors in the quoted C++ project that
]were not caught by testing and are still in the production code? 
]
]I'll tell you. They are not type errors.

Nope, you can't tell that.  C++ production code can core dump due to a
type error.  That's because to implement something that really needs
dynamic typing you often have to use tricks that leave all type
checking up to the programmer.

What can you say about errors that occur in  production code in
dynamically typed languages?  First, they are not caused by the
necessity of getting around the static type checker.  Second, they are
almost never type errors of the sort that could have been caught by a
static type checker.  Third, if they are type errors they cannot cause
a core dump or other unpredictable behavior.
--
					David Gudeman
gudeman@cs.arizona.edu
noao!arizona!gudeman

sfk@otter.hpl.hp.com (Steve Knight) (04/17/91)

Drew writes:
> The only experience with dynamically-typed systems I have are Lisp-based
> systems, just today I crashed one with a type error.  

If your system crashed, it has a serious bug.  Type errors should be caught at
run-time and put you into a debugging loop.

[Drew also suggests ML as being a serious strongly typed system.]
I had a similar type problem with ML, too.   I found a hole in the type checker
of my implementation & took a long time finding it.  It was a serious bug in
the implementation -- but not the language.  Similarly, your LISP bug
is a bug in the implementation.

Furthermore, there's not much point in taking C to task for having (void *),
when mostly every implementation of ML has the equivalent of New Jersey's
    System.Unsafe.cast : 'a -> 'b
I only say "mostly" because I don't know about POLY/ML.  (But I'll take a bet.)
This little charmer is even worse than (void *).

Admittedly, it isn't part of the language -- which is almost worse.  If some
one uses it, then the code has to be changed before it can be ported.  I 
don't like the idea of changing code that has been written using this
monstrosity.  If I am going to use packages that require it, then I will
trust the implementor to get it right once.

Steve

mathew@mantis.co.uk (mathew) (04/17/91)

dnsurber@lescsse.jsc.nasa.gov (Douglas Surber) writes:
> In <1917@optima.cs.arizona.edu> gudeman@cs.arizona.edu (David Gudeman) writes
> >If they
> >hadn't caught those errors by static typing they would have caught
> >them by testing -- the same way the found the other 90% of the errors.
> >This logic error combined with the strident tone of the article
> >suggests that your convictions are affecting your thinking.
> 
> The real question is how long would it take them to catch those errors
> by testing?  The type checker catches them all first time every time.
> Admittedly not every error, but reducing the number of errors by 10%
> before you even begin testing sounds like a win to me.  

What, even if your code has to be twice as long and twice as complicated and
take three times as long to write, because you're writing it in a
statically-typed language?

Yes, if the program you're writing is NOT best expressed in a
dynamically-typed way, then go ahead and use static typing. But saying that
static typing is ALWAYS the best solution is just blinkered stubbornness.


mathew

--
If you're a John Foxx fan, please mail me!

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/18/91)

In article <2023@optima.cs.arizona.edu> gudeman@cs.arizona.edu (David Gudeman) writes:
> And the errors that can be caught by static type checking are almost
> universally so trivial that they probably all _would_ be caught by
> testing.

Goofus uses dynamic typing. Gallant uses static typing.

Goofus says static typing catches so few errors that they probably all
_would_ be caught by testing. Gallant simply catches all the errors.

Goofus finds 95% of the typing bugs during testing. Gallant finds 100%.

Management fires Goofus.

---Dan
P.S. 1/2 :-) for the humor-impaired.

dmg@ssc-vax.uucp (David M Geary) (04/18/91)

]  David Gudeman
]] Douglas Surber

]If they hadn't caught those errors by static typing they would have caught
]them by testing -- the same way the found the other 90% of the errors.
]This logic error combined with the strident tone of the article
]suggests that your convictions are affecting your thinking.

]]The real question is how long would it take them to catch those errors
]]by testing?  The type checker catches them all first time every time.
]]Admittedly not every error, but reducing the number of errors by 10%
]]before you even begin testing sounds like a win to me.  

  Sounds like a win to me, also.  However, there are two caveats:
  
1)  Since dynamic typing allows more expressiveness and a greater degree
    of reusability than a statically typed language, code in a statically 
    typed language may be 10% (or more) larger than the "same" code in a 
    dynamically typed language.  So, while some errors have been ironed out
    before testing, testing may have more to test.

2)  Errors caused by circumvention of the type system in a statically typed
    language may *not* be caught by the compiler, and are difficult to
    track down.  In fact, I demonstrated such an error in an earlier posting.

]]Further, the type checker finds type errors even in code that, for one
]]reason or another, is never excersized during testing.  Again not every
]]error, but a 10% reduction is still something.

  Again, realize that the type checker will not find errors that fall into
category #2 above.

barmar@think.com (Barry Margolin) (04/18/91)

In article <2023@optima.cs.arizona.edu> gudeman@cs.arizona.edu (David Gudeman) writes:
>What can you say about errors that occur in  production code in
>dynamically typed languages?  First, they are not caused by the
>necessity of getting around the static type checker.  Second, they are
>almost never type errors of the sort that could have been caught by a
>static type checker.  Third, if they are type errors they cannot cause
>a core dump or other unpredictable behavior.

The above assumes that a dynamically typed language always does type
checking.  Common Lisp, for instance, does not require runtime type
checking.  The following has unpredictable behavior:

(rplaca (read) 3)

If the input does not contain the representation of a cons then it has
undefined behavior, and can core dump, corrupt the Lisp image, or launch a
nuke.

A static type checker could flag this as a potential type error, but it
shouldn't disallow the code.  If the input is coming from the user I'd
consider the above to be poor code, but if it is coming from a
machine-generated source that is "guaranteed" to have the representation of
a cons, then it is safe; for instance, the following is fine:

(with-input-from-string (*standard-input* (format nil "(~S)" object))
  (rplaca (read) 3))

is guaranteed to return the same thing as

(list 3)

or signal a read-error if OBJECT doesn't have a readable printed
representation.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

barmar@think.com (Barry Margolin) (04/18/91)

In article <8189:Apr1719:16:2091@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Goofus uses dynamic typing. Gallant uses static typing.
...
>Management fires Goofus.

>
>Goofus says static typing catches so few errors that they probably all
>_would_ be caught by testing. Gallant simply catches all the errors.
>
>Goofus finds 95% of the typing bugs during testing. Gallant finds 100%.
>

Goofus uses dynamic typing with automatic runtime type checking.  Gallant
uses static type checking, with no runtime type checking (except perhaps
that explicitly programmed by Gallant, e.g. variant record discriminant
examination).

Goofus says static typing catches very few errors that aren't caught by
runtime type checks during testing, and doesn't catch any of the errors
that are not detectable statically (e.g. misuse of unions and pointer
casting).

Goofus finds 95% of the statically detectable typing bugs, and 95% of the
non-statically detectable typing bugs.  Gallant finds 100% of the
statically detectable typing bugs, and 5% of the non-statically detectable
typing bugs (the ones that happen to result in core dumps).

The winner depends on the style of the program.  Users of statically-typed
languages often limit themselves (perhaps unconsciously) to using the
subset of the language that is easy to check statically.  Then they declare
that dynamic checking isn't needed, because static checking is able to find
all their type errors.

I feel similarly about array bounds checking.

Actually, I think a good solution is a compromise, a la Common Lisp and
some polymorphic functional languages.  The programmer may include optional
type declarations, and the compiler should do type propogation.  Where the
compiler can prove type safety, it doesn't need to insert runtime type
checks; when it can't, it puts in the checks.  I've read about similar
schemes for optimizing away most array bounds checks.

--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

jls@rutabaga.Rational.COM (Jim Showalter) (04/18/91)

%>]>	Some info that I picked up from a company doing a lot of big
%>]>	project work with C++ (i.e. strong type checking language) was
%>]>	that postmortems on their project revealed only 10% of their
%>]>	errors were captured by strong type checking.
%>]...
%>]In any other field of engineering, a 10% increase in safety would always
%>]be applied.  To reject it would be grounds for lawsuits, at least.
%
%>How do you get a 10% increase in safety from the above?  If they
%>hadn't caught those errors by static typing they would have caught
%>them by testing -- the same way the found the other 90% of the errors.
%>This logic error combined with the strident tone of the article
%>suggests that your convictions are affecting your thinking.

Bzzzzzzt. Thank you for playing.

Testing is NOT guaranteed to catch these errors, whereas static typing
is, by its nature, guaranteed to do so. I defy you to come up with a
way to ensure that you have traversed all possible paths through a
dynamically-typed program that could conceivably send the wrong message
to the wrong recipient.

Last time I looked, this sort of coverage-with-range-tracking stuff
was NP-hard, which means for any program of reasonable size you'd have
to test it for more years than there are atoms in the universe to
exhaust all possible ways it could go bump.

Nobody is claiming that there are not ways to go bump in statically-typed
languages, only that the number of ways you can go bump is REDUCED. 
Such risk reduction seems to me to be a fine way to increase program
reliability, which seems like a noble goal. Why anybody would deliberately
choose to code in a language that is guaranteed to permit MORE errors
than another language is beyond me.
--
* The opinions expressed herein are my own, except in the realm of software *
* engineering, in which case I borrowed them from incredibly smart people.  *
*                                                                           *
* Rational: cutting-edge software engineering technology and services.      *

sakkinen@jyu.fi (Markku Sakkinen) (04/18/91)

In article <2023@optima.cs.arizona.edu> gudeman@cs.arizona.edu (David Gudeman) writes:
>In article  <1991Apr15.234559.16293@comp.vuw.ac.nz> Brian Boutel writes:
> ...
>]The claim that testing catches all errors is laughable.
>
>Sure is.  Did someone make that claim?

That is how I too have understood several of your postings.
You have even added "in a matter of minutes".
Glad to hear you don't really think so.

> ...
>]So what can be said about all the errors in the quoted C++ project that
>]were not caught by testing and are still in the production code? 
>]
>]I'll tell you. They are not type errors.
>
>Nope, you can't tell that.  C++ production code can core dump due to a
>type error.  That's because to implement something that really needs
>dynamic typing you often have to use tricks that leave all type
>checking up to the programmer.

C and C++ are a bad choice to represent statically typed languages
in these comparisons.  C descends from some truly _untyped_ languages
and that still shows.  It has only partial type checking at compile
time and none whatsoever at run time.  C++ is not essentially better.

>What can you say about errors that occur in  production code in
>dynamically typed languages?  First, they are not caused by the
>necessity of getting around the static type checker.  Second, they are
>almost never type errors of the sort that could have been caught by a
>static type checker.  Third, if they are type errors they cannot cause
>a core dump or other unpredictable behavior.

However, there are situations in which "Message not understood"
is not essentially better than a core dump.  Typically, embedded
systems running unoperated.

Markku Sakkinen
Department of Computer Science and Information Systems
University of Jyvaskyla (a's with umlauts)
PL 35
SF-40351 Jyvaskyla (umlauts again)
Finland
          SAKKINEN@FINJYU.bitnet (alternative network address)

cs450a03@uc780.umd.edu (04/18/91)

Jim Showalter writes:

>Bzzzzzzt. Thank you for playing.

*sigh* *yawn*

>I defy you to come up with a way to ensure that you have traversed
>all possible paths through a dynamically-typed program that could
>conceivably send the wrong message to the wrong recipient.

Design the program so that there are only a small number of paths in
any given module.  Test each module before using.

One of the advantages of dynamic typing is that it allows you to
represent information as data which, in a statically typed language,
can only be represented as control flow.

Raul Rockwell

gudeman@cs.arizona.edu (David Gudeman) (04/19/91)

In article  <jls.671951286@rutabaga> Jim Showalter writes:
]%
]%>...  If they
]%>hadn't caught those errors by static typing they would have caught
]%>them by testing -- the same way the found the other 90% of the errors.

]Bzzzzzzt. Thank you for playing.

Bzzzzzzt.  Thank you for being obnoxious.  That might have been funny
the first time it was done, but it is getting really old.  Especially
as it is usually done by people who demonstrably know no more than the
person they are replying to.

]Testing is NOT guaranteed to catch these errors, whereas static typing
]is, by its nature, guaranteed to do so.

No, it isn't guaranteed.  But it will catch most of them, and I claim
that the tradeoff (static typing _causes_ some errors that aren't
caught) is in favor of dynamic typing.

]I defy you to come up with a
]way to ensure that you have traversed all possible paths through a
]dynamically-typed program that could conceivably send the wrong message
]to the wrong recipient.

Ooh.  I've been defied.  Well lets see, this should take about 3
seconds...  OK, write a type inferencer.  (Not that I think this is
obviously worth doing.)

]Nobody is claiming that there are not ways to go bump in statically-typed
]languages, only that the number of ways you can go bump is REDUCED. 

People aren't just claiming that, they are assuming it.  I think they
need to question their assumptions.

]... Why anybody would deliberately
]choose to code in a language that is guaranteed to permit MORE errors
]than another language is beyond me.

See what I mean?  Assuming that dynamic typing has more errors.
Completely without evidence, I might add (or repeat actually).
--
					David Gudeman
gudeman@cs.arizona.edu
noao!arizona!gudeman

barmar@think.com (Barry Margolin) (04/19/91)

In article <2400043@otter.hpl.hp.com> sfk@otter.hpl.hp.com (Steve Knight) writes:
>Drew writes:
>> The only experience with dynamically-typed systems I have are Lisp-based
>> systems, just today I crashed one with a type error.  
>If your system crashed, it has a serious bug.  Type errors should be caught at
>run-time and put you into a debugging loop.

Not if you've turned off runtime type checking:

(proclaim '(optimize (speed 3) (safety 0)))

declares that the programmer wants the code to go as fast as possible, and
doesn't want any time wasted on unnecessary type checking ("necessary" type
checking is that which is needed to implement generic functions).

When you make such a declaration, type problems become the programmer's
problem, just like in statically-typed languages.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

bertrand@eiffel.UUCP (Bertrand Meyer) (04/19/91)

From article <3865@ssc-bee.ssc-vax.UUCP>
by dmg@ssc-vax.uucp (David M Geary):

> 1)  Since dynamic typing allows more expressiveness and a greater degree
>     of reusability than a statically typed language, code in a statically 
>     typed language may be 10% (or more) larger than the "same" code in a 
>     dynamically typed language.  So, while some errors have been ironed out
>     before testing, testing may have more to test.

The premise of this sentence (a statically typed language is less
expressive) is, I believe, incorrect. With the appropriate
typing facilities (in particular genericity, constrained and
unconstrained) you lose absolutely nothing in expressiveness.
This has been discussed at length in this newsgroup before,
and in spite of many efforts and even ``challenges''
I don't think anyone has shown a convincing counter-example -
something that could be expressed conveniently in a dynamically
typed language but not in a statically typed language.
(Again, I am assuming a decent type system; if you don't have
genericity, or if arbitrary C-like casts are allowed,
this is all meaningless anyway.)

Mr. Geary is quite correct, however, that a statically typed language
will be slightly more verbose because of the need for declaring
entities (attributes, local variables, function results).
But this should have at most a negligible effect on testing.
Typically, one tests the executable parts of a software system
(the instructions), not the declarations. In fact, the presence
of declarations may be a significant help in eliminating useless
tests and making each individual test more productive.
(The same applies to assertions, but that's another story.)

It is true, of course, that as soon as you introduce more text
(such as declarations) you introduce more possibilities of error.
This is because static typing follows the time-honored method
of introducing redundancy to make it easier to catch errors.
The reason this is a good method is that more
redundancy means more likelihood that a conceptual error will
become an *inconsistency*, and inconsistencies are always
much easier to detect than more general types of errors.
The catch is that you may then detect inconsistencies which
are *not* original errors: for example, they may result from errors
in the elements that have been added for redundancy. (This occurs
for example when a variable is used properly, but its declaration
is ``wrong'' with respect to the programmer's intent.)

This means that when you add redundancy for security there is a risk
of false alarm (detecting an apparent error when the original was in
fact correct). If, as is the case in the practice of reasonable
statically typed languages, such false alarms are rare, the price
is acceptable, being justified by all the *real* alarms that
redundancy will enable you to catch.

As an analogy (offered for what it's worth), in some countries
elementary school students are (were?) taught to check
an arithmetic operation by ``crossing out nines'' (``preuve par 9''),
which is a quick modulo-9 check. Once in a while you will find
an inconsistency which results from an error in the crossing-out,
not in the original operation. However this occasional nuisance
- which merely forces you to redo the operation and the check -
is nothing to complain about when compared to all the
*real* errors that this type of checking catches.
-- 
-- Bertrand Meyer
Interactive Software Engineering Inc., Santa Barbara
bertrand@eiffel.uucp

new@ee.udel.edu (Darren New) (04/23/91)

In article <530@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:
>I don't think anyone has shown a convincing counter-example -
>something that could be expressed conveniently in a dynamically
>typed language but not in a statically typed language.

I think a "resource manager" is a good example.  By this, I mean a module
which accepts <name, object> pairs either to be stored or retrieved. 
Presumedly, the one storing and the one retrieving need to know what 
the type is, but the resource manager need not.  Sort of like an
environment-variable list, except that the right-hand side is not
restricted to single strings but rather can be any type in the
language.             - Darren
-- 
--- Darren New --- Grad Student --- CIS --- Univ. of Delaware ---
----- Network Protocols, Graphics, Programming Languages, FDTs -----
     +=+=+ My time is very valuable, but unfortunately only to me +=+=+
+=+ Nails work better than screws, when both are driven with screwdrivers +=+

diamond@jit345.swstokyo.dec.com (Norman Diamond) (04/24/91)

In article <1917@optima.cs.arizona.edu> gudeman@cs.arizona.edu (David Gudeman) writes:
>In article  <1991Apr15.065146.16680@tkou02.enet.dec.com> Norman Diamond writes:
>>In article <4243.2805b94a@iccgcc.decnet.ab.com> klimas@iccgcc.decnet.ab.com writes:
>>>	Some info that I picked up from a company doing a lot of big
>>>	project work with C++ (i.e. strong type checking language) was
>>>	that postmortems on their project revealed only 10% of their
>>>	errors were captured by strong type checking.
>>In any other field of engineering, a 10% increase in safety would always
>>be applied.  To reject it would be grounds for lawsuits, at least.
>How do you get a 10% increase in safety from the above?  If they
>hadn't caught those errors by static typing they would have caught
>them by testing -- the same way the found the other 90% of the errors.

Sorry for the delay -- I have just discovered that topics which I reply to
in comp.object somehow move into comp.lang.misc, sigh.

Anyway, 10% of the caught errors were type errors.
By grossly rough estimate, 10% of the uncaught errors are also type errors.
Strong typing would reduce the number of remaining, uncaught errors by 10%.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

objtch@extro.ucc.su.oz.au (Peter Goodall) (04/24/91)

dnsurber@lescsse.jsc.nasa.gov (Douglas Surber) writes:

>In <1917@optima.cs.arizona.edu> gudeman@cs.arizona.edu (David Gudeman) writes:

>>If they
>>hadn't caught those errors by static typing they would have caught
>>them by testing -- the same way the found the other 90% of the errors.
>>This logic error combined with the strident tone of the article
>>suggests that your convictions are affecting your thinking.

>The real question is how long would it take them to catch those errors
>by testing?  The type checker catches them all first time every time.
>Admittedly not every error, but reducing the number of errors by 10%
>before you even begin testing sounds like a win to me.  

>Further, the type checker finds type errors even in code that, for one
>reason or another, is never excersized during testing.  Again not every
>error, but a 10% reduction is still something.

This mystical 10% says nothing about the other 90%, or what is responsible
for them. They could be caused by having to rewrite code because the static
typing did not provide enough reusability :-).

--
------------------------------------------------------------------------
Peter Goodall - Smalltalk Systems Consultant - objtch@extro.ucc.su.oz.au
      ObjecTech Pty. Ltd. - Software Tools, Training, and Advice
162 Burns Bay Rd, LANE COVE, NSW, AUSTRALIA. - Telephone: +61 2 418-7433

dlw@odi.com (Dan Weinreb) (04/28/91)

In article <530@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:

   The catch is that you may then detect inconsistencies which
   are *not* original errors: for example, they may result from errors
   in the elements that have been added for redundancy. (This occurs
   for example when a variable is used properly, but its declaration
   is ``wrong'' with respect to the programmer's intent.)

   This means that when you add redundancy for security there is a risk
   of false alarm (detecting an apparent error when the original was in
   fact correct). If, as is the case in the practice of reasonable
   statically typed languages, such false alarms are rare, the price
   is acceptable, being justified by all the *real* alarms that
   redundancy will enable you to catch.

Yes, I agree completely, and here's another analogy that people might
like.  Consider parity checking on computer main memory.  Adding
parity bits allows a consistency check, so that you can easily
recognize when one of the stored bits in memory is incorrect.  The
catch is that perhaps the parity bit itself might have the wrong
value!  In this case, you actually would have been better off without
the parity bit.  However, I think most people can see why, despite
this catch, there's quite a lot to be said for the parity bit, and
most people would rather have parity checking than no checking, and
are willing to pay for it.

This isn't a perfect analogy for all aspects of the issue under
discussion, of course.  I just think it's a good way to explain the
business about the "catch", and the risk of false alarm, and why that
might not be as bad some people might at first think.  Whether the
relative costs for various kinds of software construct are similar
to the relative costs for parity checking is not necessarily obvious,
but the qualitative nature of the tradeoff is similar in this way.

cpp@calmasd.Prime.COM (Chuck Peterson) (05/03/91)

I am glad Mr. Meyer and others admit there is a cost to redundancy.

Consider that many of the languages users prefer, from novice to theoretician,
from Basic to Lisp and Smalltalk, are dynamically typed.  Both because
it simplifies ad hoc experimenting, reduces code size and manifest
complexity, and makes polymorphism natural.

Has a cost of additional error and maintenance of dynamically vs.
statically typed programming really been proven?  No doubt perfectly
unmaintainable code has been written either way, and perhaps some of
the most challenging of smaller products, such as GNU emacs, have been
written with dynamically typed languages.  (Perhaps many formidable large
products as well.)  Even if there is an additional cost,  is it not usually
outweighed by productivity and inventiveness.

Perhaps statically typed languages should be used like assembly language,
where the added security (as with performance for assembly) justifies
recoding.  (Perhaps both security and performance in some measure.)

rockwell@socrates.umd.edu (Raul Rockwell) (05/03/91)

Chuck Peterson:
> Perhaps statically typed languages should be used like assembly
> language, where the added security (as with performance for
> assembly) justifies recoding.  (Perhaps both security and
> performance in some measure.)

Perhaps I'm missing some fundamental insight, but I fail to see how
static typing provides any sort of security.

Consider an arbitrary program, with (for example) several thousand
variables and a few dozen types.  If the program says:  f(x),
what does static typing buy you, security-wise?  You can only
misidentify x a few hundred ways instead of a few thousand?  (Awesome
reliability there).

Unless you are intending to allow only one instance of a type in any
lexical name-space?  That would be security!  [And you'd be writing
your program at least twice, once in "type expressions", and once in
"imperative expressions".  There's nothing quite like trying to keep
two versions of the same thing in sync to improve reliability...]

Performance, you can get, to the extent that your compiler
pre-computes the results of your program.  ("Static typing" means
evaluate "type expressions" at compile time).

Raul Rockwell

diamond@jit533.swstokyo.dec.com (Norman Diamond) (05/09/91)

In article <ROCKWELL.91May2222805@socrates.umd.edu> rockwell@socrates.umd.edu (Raul Rockwell) writes:
>Chuck Peterson:
>> Perhaps statically typed languages should be used like assembly
>> language, where the added security (as with performance for
>> assembly) justifies recoding.  (Perhaps both security and
>> performance in some measure.)
>Perhaps I'm missing some fundamental insight, but I fail to see how
>static typing provides any sort of security.
>Consider an arbitrary program, with (for example) several thousand
>variables and a few dozen types.  If the program says:  f(x),
>what does static typing buy you, security-wise?  You can only
>misidentify x a few hundred ways instead of a few thousand?  (Awesome
>reliability there).

Exactly.  In this scenario, if you misidentify x, there is a 90% chance
that your error will be caught.  This is 9 times as valuable as a case
previously discussed, where other fields of engineering value a 10%
improvement in safety.

>Unless you are intending to allow only one instance of a type in any
>lexical name-space?  That would be security!  [And you'd be writing
>your program at least twice, once in "type expressions", and once in
>"imperative expressions".  There's nothing quite like trying to keep
>two versions of the same thing in sync to improve reliability...]

Although excessive and rhetorical, this also has its value.
Why did businesses used to use "verifiers" on their punched cards for
data entry?  Why do fault-tolerant machines compute many results twice?
You'd better believe there is nothing like redundancy to improve reliability.

When mismatches are detected (which can benefit greatly from mechanical
assistance or compilers), they can be inspected manually to see if they are
really errors, or which part has the errors.  This is far better than skipping
half of them and letting 10% or 90% of the other half remain undetected.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

rockwell@socrates.umd.edu (Raul Rockwell) (05/09/91)

me: Consider an arbitrary program, with (for example) several thousand
me: variables and a few dozen types.  If the program says: f(x), what
me: does static typing buy you, security-wise?  You can only
me: misidentify x a few hundred ways instead of a few thousand?
me: (Awesome reliability there).

Norman Diamond:
   Exactly.  In this scenario, if you misidentify x, there is a 90%
   chance that your error will be caught.  This is 9 times as valuable
   as a case previously discussed, where other fields of engineering
   value a 10% improvement in safety.

Enumerating the number of ways a variable may be misidentified does
not properly identify the chances that it will be caught.  Run-time
insanity checks can provide a degree of robustness that is not
available using only compile time checks.

Just because your language will not catch certain errors except with
static typing doesn't mean that my language has the same problem.
Also note that dynamic typing allows wonderful properties in a
debugger.

Note that I'm classifying as type checking: array bounds checking,
un-assigned variable checking, range checking, storage class checking
and exceptional values checking.  A compiler can catch some instances
of un-assigned variables, and some instances of storage class
checking.  It's not going to be able to check anything dynamic (except
the static references). A really good compiler might be able to catch
_some_ instances of value out of range.

Ultimately, making the programmer work to make sure that variable Quad
is not assigned to variable Tape is not going to do anything to make
sure that Quad is being used correctly -- it's just going to make sure
that one of many stupid mistakes is not made.

me: Unless you are intending to allow only one instance of a type in
me: any lexical name-space?  That would be security!  [And you'd be
me: writing your program at least twice, once in "type expressions",
me: and once in "imperative expressions".  There's nothing quite like
me: trying to keep two versions of the same thing in sync to improve
me: reliability...]

Norman Diamond:
   Although excessive and rhetorical, this also has its value.  Why
   did businesses used to use "verifiers" on their punched cards for
   data entry?  Why do fault-tolerant machines compute many results
   twice?  You'd better believe there is nothing like redundancy to
   improve reliability.

Why do some machines associate type with a variable at runtime?  Could
it be because there is nothing like redundancy to improve reliability?

(yeah, I'm leaving out an issue here:  additional features which come
with a typing system.  Some such features are gratuitous, some are so
significant that they make reliability arguments pale.)

Raul Rockwell

quale@khan.cs.wisc.edu (Douglas E. Quale) (05/13/91)

In article <1991May9.023313.28308@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>When mismatches are detected (which can benefit greatly from mechanical
>assistance or compilers), they can be inspected manually to see if they are
>really errors, or which part has the errors.  This is far better than skipping
>half of them and letting 10% or 90% of the other half remain undetected.
>--
>Norman Diamond       diamond@tkov50.enet.dec.com
>If this were the company's opinion, I wouldn't be allowed to post it.

This statement suggests that programs compiled in dynamic languages contain
more type errors than similar programs written in statically typed languages.
Unfortunately I don't know of any studies that have been made that could
definitively affirm or deny this.  In fact, I don't know of any evidence at
all that points one way or the other.  I think I understand why static
typing devotees believe that static typing is safer than dynamic typing,
but I think they're mistaken.  In considering the evidence presented by both
sides I show my bias by giving greater weight to those who have actually
used dynamically typed languages.  Simply stated, almost everyone experienced
in writing in dynamic languages also has experience with statically typed
languages.  The reverse is often (usually?) not the case.

Two particulars:

Dynamic typing makes program components easier to test interactively in
isolation; the components get tested again together.  You may say you do
all these tests in your statically typed language even though it's very
inconvenient.  I ask you, does everyone?  In either case I appreciate the
great saving in time and effort that an interpreter + compiler provide.
(Some statically typed languages provide interactive environments.  The
only examples that I'm familiar with are examples of type inferencing
systems much more advanced than Pascal/C/Ada type systems.  Many of these
are not as convenient to use as a dynamically typed system -- see for
instance a thread in comp.lang.functional about SML.)

Static type systems can actually be MUCH LESS SAFE than dynamic type
systems.  I mention this only because perhaps some folks haven't considered
it.  This is often a problem when a primitive static type system attempts
to emulate dynamic typing.  A specific example is provided by the X Toolkit
Intrisics.  To get information from a widget you use a call that looks like
this:

XtVaGetValues(widget, XtNwidth, &width, XtNheight, &height, NULL);

Unfortunately width and height are type XtArgVal which is a union which
completely defeats any typechecking.  The correct type is Dimension, should
I instead use int I get no help from the compiler, and my code has a type
error.  This kind of type error CANNOT occur in a dynamically typed
language.

-- Doug Quale
quale@khan.cs.wisc.edu

ajk@wren.cs.rmit.OZ.AU (Alan Kent) (05/13/91)

quale@khan.cs.wisc.edu (Douglas E. Quale) writes:

>This statement suggests that programs compiled in dynamic languages contain
>more type errors than similar programs written in statically typed languages.
>Unfortunately I don't know of any studies that have been made that could
>definitively affirm or deny this.  In fact, I don't know of any evidence at
>all that points one way or the other.

I also do not know of any studies, and have been a little swayed
towards dynamic typing by the arguments presented in this group.
However I still have some doubts. For example, what calibre are the
programmers who are using these dynamic languages? For large projects
out in industry, it is less likely that you will have a team of
hot-shot programmers. Good programmers are likely to do a good job in
any language. But what about the not so good programmers. Maybe they
need more hand-holding as provided by a static language. Are most of
the people using dynamic languages more research oriented (and so
hopefully better trained)?

The other argument I have for static typing is that it is a form of
very formal documentation. Using types specifies exactly how you expect
a piece of code to be used - exactly what values can be passed to a
function and what can be returned from a function. Sure, a clever
compiler may be able to determine these things. But that is not a form
of documentation for users. Sure, you could just use comments. But from
my limited experience in large projects, its very easy to get lazy and
leave some out. Most software does not just have to get written.
It has to be maintained later, often by someone who did not write
the original program.

My main complaint with static typing is that there are not many
languages that do a good job of it. C is pretty bad. Pascal is too
inflexible.  Eiffel, while it may have problems, is certainly a step
better. It seems to me it is not the concept of static typing which is
the problem, but rather that not many statically typed languages do a
very good job.

Oh well, that is my 2 cents worth, if its worth even that! :-)

Dr Alan Kent
Comp Sci, RMIT, Melbourne, Australia
ajk@goanna.cs.rmit.oz.au

diamond@jit533.swstokyo.dec.com (Norman Diamond) (05/13/91)

In article <1991May13.061520.11992@daffy.cs.wisc.edu> quale@khan.cs.wisc.edu (Douglas E. Quale) writes:
>In article <1991May9.023313.28308@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>>When mismatches are detected (which can benefit greatly from mechanical
>>assistance or compilers), they can be inspected manually to see if they are
>>really errors, or which part has the errors.  This is far better than skipping
>>half of them and letting 10% or 90% of the other half remain undetected.
>
>This statement suggests that programs compiled in dynamic languages contain
>more type errors than similar programs written in statically typed languages.

Try:  a smaller percentage of the type errors are caught.
To prove this would require translation from an untyped language to a typed
language, taking care to assign correct types but without correcting errors
that are caught at that stage -- then seeing what a compiler would catch.
I also don't know anyone who has done this kind of arcane study.

In general, some studies have shown that the ratio of bugs remaining in a
program (to the size of the program) tends to be proportional to the ratio
of bugs that have been caught and removed.  This relationship is not an
inverse one.  Of course, if the product lives long enough and newly caught
bugs decline in frequency, then one might expect remaining uncaught bugs
to have declined similarly.

I suggested as a rough approximation that each KIND of error shows similar
behavior, except when the compiler prevents certain kinds of errors.

>In considering the evidence presented by both
>sides I show my bias by giving greater weight to those who have actually
>used dynamically typed languages.

In chronological order, APL, Snobol, Unix shell and other command languages,
and Smalltalk.

>Dynamic typing makes program components easier to test interactively in
>isolation; the components get tested again together.  You may say you do
>all these tests in your statically typed language even though it's very
>inconvenient.

I didn't see it as inconvenient.  Now, some people see testing as
inconvenient, but I haven't heard typing asserted as the reason.

>I ask you, does everyone?

This is really an irrelevant question.  It is possible to code untested
programs in every language.  There will never be a language in which it
is impossible to write untested programs.

If a developer WANTS to be incompetent, maybe static vs. dynamic doesn't
matter -- well, maybe it does ... if a programmer wants to be incompetent
and lazy, then dynamic has its advantages.  (PLEASE NOTE:  this is not
intended as a slur against dynamic typing, or against valid arguments
for dynamic typing.  In fact, I also need dynamic typing on occasion.)

>Static type systems can actually be MUCH LESS SAFE than dynamic type systems.

Static typing is not less safe than dynamic typing.  Escapes from static
typing can certainly be unsafe, and incompetent escapes most likely are.

>A specific example is provided by the X Toolkit Intrisics.
>To get information from a widget you use a call that looks like this:
>  XtVaGetValues(widget, XtNwidth, &width, XtNheight, &height, NULL);
>Unfortunately width and height are type XtArgVal which is a union which
>completely defeats any typechecking.  The correct type is Dimension, should
>I instead use int I get no help from the compiler, and my code has a type
>error.  This kind of type error CANNOT occur in a dynamically typed
>language.

It could occur in a dynamically typed language, if the programmer can tell
the language to throw away tagging and type-checking.  A competent programmer
would put a tag in the union type.  (C is not an encouraging language for
this kind of practice, but it still could be done.)
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

quale@saavik.cs.wisc.edu (Douglas E. Quale) (05/15/91)

In article <1991May13.082152.29294@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>In article <1991May13.061520.11992@daffy.cs.wisc.edu> quale@khan.cs.wisc.edu (Douglas E. Quale) writes:
>
>>A specific example is provided by the X Toolkit Intrisics.
>>To get information from a widget you use a call that looks like this:
>>  XtVaGetValues(widget, XtNwidth, &width, XtNheight, &height, NULL);
>>Unfortunately width and height are type XtArgVal which is a union which
>>completely defeats any typechecking.  The correct type is Dimension, should
>>I instead use int I get no help from the compiler, and my code has a type
>>error.  This kind of type error CANNOT occur in a dynamically typed
>>language.
>
>It could occur in a dynamically typed language, if the programmer can tell
>the language to throw away tagging and type-checking.  A competent programmer
>would put a tag in the union type.  (C is not an encouraging language for
>this kind of practice, but it still could be done.)
>

In lisp, the most ``common'' dynamically typed language, you cannot throw away
tagging.  You are, however, somewhat at the mercy of the compiler in regards
to type checking unless you explicitly make the checks yourself.

But the fact is, this particular error does NOT occur in a dynamically typed
language.  If you or anyone else reading this is familiar with the X
Toolkit Intrinsics and can see a way to avoid this problem I'd like to hear
about it.  The designers of the Intrinsics found that C's static typing
wasn't adequate for their needs and built an unchecked dynamic type system
on top of it.  Now C's type system is very primitive, but I'm not certain
that any static type system is flexible enough to handle this problem.  The
most promising approach might be a statically typed object oriented language.

-- Doug Quale
quale@saavik.cs.wisc.edu

olson@juliet.ll.mit.edu ( Steve Olson) (05/15/91)

In article <1991May15.141839.20603@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
   In lisp, the most ``common'' dynamically typed language, you cannot throw away
   tagging.

Careful, there is no single thing called "lisp".  (Its more like a state
of mind :-) This is exactly what an optimizing Common Lisp compiler will do.
Spectacular errors (worthy of C :-) will result if you lie when you make
your type declarations.

--
-- Steve Olson
-- MIT Lincoln Laboratory
-- olson@juliet.ll.mit.edu
--

diamond@jit533.swstokyo.dec.com (Norman Diamond) (05/16/91)

In article <1991May15.141839.20603@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
>In article <1991May13.082152.29294@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>>In article <1991May13.061520.11992@daffy.cs.wisc.edu> quale@khan.cs.wisc.edu (Douglas E. Quale) writes:
>>>  XtVaGetValues(widget, XtNwidth, &width, XtNheight, &height, NULL);
>>>Unfortunately width and height are type XtArgVal which is a union which
>>>completely defeats any typechecking.
>>>This kind of type error CANNOT occur in a dynamically typed language.
>>
>>It could occur in a dynamically typed language, if the programmer can tell
>>the language to throw away tagging and type-checking.  A competent programmer
>>would put a tag in the union type.
>
>In lisp, the most ``common'' dynamically typed language, you cannot throw away
>tagging.

I did say "if".

>But the fact is, this particular error does NOT occur in a dynamically typed
>language.

It could be made to occur.  (Not that I would recommend it, of course.)

>If you or anyone else reading this is familiar with the X Toolkit Intrinsics
>and can see a way to avoid this problem I'd like to hear about it.

As I said, C is not an encouraging language for it, but a competent programmer
could put a tag in.  (C allows a programmer to support dynamic typing, though
C itself does not support it, and in fact cumbersome syntax discourages it.)

typedef enum XtArgTag {
        XtArgCaddr,
        XtArgCharPtr,
        XtArgLong,
        XtArgIntPtr,
        XtArgProcPtr,
} XtArgTag;
typedef union XtArgUnion {
        caddr_t     Caddr;
        char       *CharPtr;
        long        Long;
        int        *IntPtr;
        proc       *ProcPtr;
} XtArgUnion;
typedef struct XtArgVal {
        XtArgTag    Tag;
        XtArgUnion  Val;
} XtArgVal;

(I have tried to maintain the same style as the typename "XtArgVal".
My personal naming style conflicts with a Posix standard.)

>The designers of the Intrinsics found that C's static typing wasn't adequate

Of course.

>and built an unchecked dynamic type system on top of it.

That's their problem.  And then they made life difficult for their clients.

>Now C's type system is very primitive, but I'm not certain
>that any static type system is flexible enough to handle this problem.

Pascal handled this problem -- and the syntax deliberately encouraged this
kind of checking.

>most promising approach might be a statically typed object oriented language.

Of course, object orientation is useful, but object orientation is really
orthogonal (or nearly so) to issues of static vs. dynamic typing.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

quale@saavik.cs.wisc.edu (Douglas E. Quale) (05/16/91)

One of the difficulties that proponents of static typing have in convincing
folks who enjoy the benefits of dynamic typing to switch is that the type
systems of the most popular statically typed languages are very primitive
and inflexible.  Compare C/Pascal/Ada to Common Lisp, for instance.
The claimed benefit of extra safety simply doesn't exist with most C
compilers.  ANSI C is a big improvement in this regard but backward
compatibility is a real hindrance to type safety.

Another issue is that _very_ often I don't care what type a value is.  It
may be the result of a library call and then simply be fed into another call.
For instance, I recently spent more than a couple of minutes figuring out
what was wrong with a C program with this fragment:

{
	...
	double f, foo;
	int i;

	...

	f = modf(foo, &i);
	...
	switch (i) { ... }
}

This is a type error that the $%#!!% compiler didn't catch (Yes, I did
include math.h).  All that was done with i was to use it in a switch
statement, and no runtime errors occured, it just gave the wrong answers
(i was always 0).  It wasn't immediately obvious that the modf call was to
blame, but once I got that far checking the man page I found that modf is
double modf(double, *double).  Changing i to double fixed the problem.
(This error occured because a certain useless pocket reference to the C
libraries said i should be int.  I'm glad I didn't pay anything for it,
or I'd be even more pissed.)

Ada would have caught this type error, but among other things I don't have
an Ada compiler.  (Even if I did, I'd have to learn Ada to be able to get
much use from it. :)

The point is, I don't care what numeric type i is.  In a dynamically typed
language this type error would not occur.  In dynamically typed languages
a lot of things that can be type errors in static languages simply *cannot*
cause errors.  I think much of the belief in the extra safety of statically
typed languages is based on experience with C, where uncaught type errors
are a common and serious problem.  C is a terrible example that gives all
of the disadvantages of static typing with very little safety in return.

-- Doug Quale
quale@saavik.cs.wisc.edu

quale@picard.cs.wisc.edu (Douglas E. Quale) (05/16/91)

In article <1991May16.011804.21042@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>
>typedef enum XtArgTag {
>        XtArgCaddr,
>        XtArgCharPtr,
>        XtArgLong,
>        XtArgIntPtr,
>        XtArgProcPtr,
>} XtArgTag;
>typedef union XtArgUnion {
>        caddr_t     Caddr;
>        char       *CharPtr;
>        long        Long;
>        int        *IntPtr;
>        proc       *ProcPtr;
>} XtArgUnion;
>typedef struct XtArgVal {
>        XtArgTag    Tag;
>        XtArgUnion  Val;
>} XtArgVal;
>

I think there are reasons why the X Toolkit Intrinsics doesn't do this.
One of the design goals was binary compatibility with past versions.

Notice that when you are forced to simulate dynamic typing in a statically
typed language you can't do it as well as a dynamically typed language can.
The explicit tags are bulky and slow compared to the representation tricks
used by lisp compilers.  Also the syntax is abominable, as you mentioned.

To boot, when (or in my case more likely if) I write my own widget and
introduce a new arg type I have to use Caddr, and type safety is shot to hell.
Dynamically typed languages are safer than primitive statically typed
languages such as C.

-- Doug Quale
quale@picard.cs.wisc.edu

quale@picard.cs.wisc.edu (Douglas E. Quale) (05/16/91)

In article <OLSON.91May15145347@goneril.juliet.ll.mit.edu> olson@juliet.ll.mit.edu ( Steve Olson) writes:
>In article <1991May15.141839.20603@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
>   In lisp, the most ``common'' dynamically typed language, you cannot throw away
>   tagging.
>
>Careful, there is no single thing called "lisp".  (Its more like a state
>of mind :-) This is exactly what an optimizing Common Lisp compiler will do.
>Spectacular errors (worthy of C :-) will result if you lie when you make
>your type declarations.
>

Yes, this can happen but in general Common Lisp doesn't get rid of the tags
(because it can't).  Suppose foo takes a single integer argument.  If foo
is visible to the world the CL compiler can't find every invocation at
compile time and so the call (foo 0) will require 0 to be tagged.  It is
possible to give foo two entry points, one for regular boxed data calls and
another for unboxed data, but in general the tag will be there.  Usually
optimization tells the compiler not to look at the tags.  This can cause
spectacular failures.

You can shoot yourself in the foot in practically any language, but a
language like C encourages unportable, unsafe practices.  In Common Lisp
it's more work to write unsafe code than safe code.

-- Doug Quale
quale@picard.cs.wisc.edu

cok@islsun.Kodak.COM (David Cok) (05/17/91)

In article <1991May16.134106.24421@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
>For instance, I recently spent more than a couple of minutes figuring out
>what was wrong with a C program with this fragment:
>
>{
>	...
>	double f, foo;
>	int i;
>
>	...
>
>	f = modf(foo, &i);
>	...
>	switch (i) { ... }
>}
>
>This is a type error that the $%#!!% compiler didn't catch (Yes, I did
>include math.h).  All that was done with i was to use it in a switch
>statement, and no runtime errors occured, it just gave the wrong answers
>(i was always 0).  It wasn't immediately obvious that the modf call was to
>blame, but once I got that far checking the man page I found that modf is
>double modf(double, *double).  Changing i to double fixed the problem.
>(This error occured because a certain useless pocket reference to the C
>libraries said i should be int.  I'm glad I didn't pay anything for it,
>or I'd be even more pissed.)

It is well(?) known that C does NO type checking on arguments to subroutines,
even with appropriate include files (prototypes weren't invented yet).  But
if you are using C you really ought to use lint to add to the rudimentary
type checking in the compiler.  That still leaves lint+C with both an
inadequate type system and inadequate type checking, but in some
environments we have to live with it.  It would have caught this error.

>
>The point is, I don't care what numeric type i is.  In a dynamically typed
>language this type error would not occur.  

It seems to me it still would:  if modf returned for you an i which was a double
and the switch statement knew only how to handle int's, you would get a
runtime error because of mismatched types.  (If you allow for smarter switch
statements or implicit conversion, you've changed the comparison to one of
flexibility of the type system rather than static vs. dynamic typing.)

> In dynamically typed languages
>a lot of things that can be type errors in static languages simply *cannot*
>cause errors.  
I believe that most dynamically typed languages have more flexible type
systems than most statically typed systems, but I need convincing on the 
point above.  Separate the issue of the type system from dynamic vs. static.
Suppose you had two languages with the same type system (e.g. same set of
functions and operators accepting the same sets of types of arguments), but
one was statically typed and the other dynamically typed.  The dynamically
typed language would catch all type errors at runtime, presumably with good
diagnostics about just what variables and types and functions were involved.
The statically typed system would catch some type errors at compile time.  
The ones it did not catch would cause difficult to find errors -- at least
they do in traditional C.  The same set of errors would occur.  So I do not
understand why "a lot of things that can be type errors in static languages 
simply *cannot* cause errors [in a dynamically typed language]".

The issue of uncaught type errors is actually because the statically typed
language is insufficiently *strong*, not because it is static.  There are
three variables that get confused in these discussions:
		expressiveness of the type system
		dynamic vs. static
		strong vs. weak

>I think much of the belief in the extra safety of statically
>typed languages is based on experience with C, where uncaught type errors
>are a common and serious problem.  C is a terrible example that gives all
>of the disadvantages of static typing with very little safety in return.

C is a prime example of static weak typing (weak in the sense that not all type
errors are caught at either run or compile time); I see no reason why any
current compiler should not be strong for an ANSI-C type language, barring
language allowed loopholes (like pointer casting).  I see no reason why anyone
would develop a dynamic weak language.  Newer static languages (e.g. C++) are
strong with loopholes ("segmentation fault" with termination being as bad for
the user as "message not understood" followed by termination).
Furthermore, if you count domain errors (such as divide by zero) as type errors,
no language is completely statically typed; it may still be strong if that error
is caught and reported at run-time; out-of-range errors are sometimes uncaught 
(e.g. C), and sometimes are caught at run-time (always or switchable at 
compile time).   So we are left with
		strong dynamic languages
		strong mostly static languages

With the *same type system* these will catch the *same* errors -- and I'd
rather catch as many at compile-time as possible.  BUT,  it seems to me that
it is much easier to provide a more flexible type system in a dynamically
typed environment; languages which have appeared to date bear this out (the
presence of type loopholes in at least some static languages is a tacit
admission that the type system is not flexible enough).  And
flexibility in typing is important for reuse of code and hence for quick
prototyping.  The challenge is to provide a flexible type system in which the 
compiler can do sufficient type analysis so that (a) as many type errors are 
reported by the compiler as is feasible (b) as many type tags are optimized 
away as is possible and (c) the rest of the potential errors are dynamically 
checked.  This would give a strong expressive language with a mixture of 
static and dynamic typing.  Maybe the compiler would even give switches -t0 .. 
-t9 trading off speed of compilation vs. amount of static/dynamic checking.

David R. Cok
Eastman Kodak Company
cok@Kodak.COM

olson@juliet.ll.mit.edu ( Steve Olson) (05/17/91)

In article <1991May16.134106.24421@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
   The point is, I don't care what numeric type i is.  In a dynamically typed
   language this type error would not occur.  In dynamically typed languages
   a lot of things that can be type errors in static languages simply *cannot*
   cause errors.  I think much of the belief in the extra safety of statically
   typed languages is based on experience with C, where uncaught type errors
   are a common and serious problem.  C is a terrible example that gives all
   of the disadvantages of static typing with very little safety in return.

   -- Doug Quale
   quale@saavik.cs.wisc.edu


I agree with that, but as was pointed out to me previously, when we think we 
are debating static vs. dynamic typing, we sometimes are actually debating
abstract types vs. machine types.  I think that a lot of type errors come when
types that are conceptually very similar to a human are not at all the same to
the machine.  

I make an order of magnitude more type errors in Common Lisp when I insert 
type declarations for optimizing purposes.  All of a sudden the difference 
between int and float and whatever becomes very important, and it *is* hard 
to keep it all straight without help from the compiler.

--
-- Steve Olson
-- MIT Lincoln Laboratory
-- olson@juliet.ll.mit.edu
--

diamond@jit533.swstokyo.dec.com (Norman Diamond) (05/17/91)

In article <1991May16.153308.4054@spool.cs.wisc.edu> quale@picard.cs.wisc.edu (Douglas E. Quale) writes:
>In article <1991May16.011804.21042@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>>[ugly C syntax to do programmer-computed dynamic typing of some X11 values]
>I think there are reasons why the X Toolkit Intrinsics doesn't do this.
>One of the design goals was binary compatibility with past versions.

Uh, if you want binary compatibility between existing C code and a
dynamically-typed language, you'll have a lot of problems.  When we
were discussing whether static typing eliminates all possibility of
tagging and type-checking, I thought we were talking about programs
that might be written by competent programmers, not about binary
compatibility with random nonsense.

>Notice that when you are forced to simulate dynamic typing in a statically
>typed language you can't do it as well as a dynamically typed language can.

Of course.  I did say that when dynamic typing is necessary, the programmer
should be able to tell the compiler to do it; and when efficiency or strict
early static checking are necessary, the programmer should be able to tell
the compiler to do that too.  And that C is not an encouraging basis for
programmer simulation of either of these.

>The explicit tags are bulky and slow compared to the representation tricks
>used by lisp compilers.  Also the syntax is abominable, as you mentioned.

Yes.  And as I said, the Pascal language supported exactly this kind of tag,
and nothing would stop a Pascal compiler from using representation tricks.
(Although if the programmer for some reason demands ord() of the tag, then
there will have to be code to convert from the tricky representation.)

>Dynamically typed languages are safer than primitive statically typed
>languages such as C.

No.  Dynamically typed languages are safer than C.  Statically typed
languages are also safer than C.  Languages that permit the programmer to
specify each kind of typing when necessary will be safer than all of the above.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

quale@saavik.cs.wisc.edu (Douglas E. Quale) (05/17/91)

In article <1991May16.175340.25522@kodak.kodak.com> cok@islsun.Kodak.COM (David Cok) writes:
>In article <1991May16.134106.24421@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
>>For instance, I recently spent more than a couple of minutes figuring out
>>what was wrong with a C program with this fragment:
>>
>>{
>>	...
>>	double f, foo;
>>	int i;
>>
>>	...
>>
>>	f = modf(foo, &i);
>>	...
>>	switch (i) { ... }
>>}
>>
>>The point is, I don't care what numeric type i is.  In a dynamically typed
>>language this type error would not occur.  
>
>It seems to me it still would:  if modf returned for you an i which was a double
>and the switch statement knew only how to handle int's, you would get a
>runtime error because of mismatched types.  (If you allow for smarter switch
>statements or implicit conversion, you've changed the comparison to one of
>flexibility of the type system rather than static vs. dynamic typing.)
>

Yes.  I'd get an error _and_an_error_message_ the first time I tried the code.
C gives me no error message, just the wrong answer.  IMHO the lisp behavior
is infinitely better in this regard.  Are you actually defending silently
giving the wrong answer to "Error in switch: expected an int but got a double"
??????  This bug gets fixed in a dynamic language in the first pass, utterly
trivially.  What makes you so certain that the programmer would even know
that the C version was bugged?  No error messages are given.  What if the
program just happens to give the expected answers on the test cases despite
the bug?  I'd consider this an overwhelming victory for the dynamically typed
language.  Guarranteed to find the bug, trivial to fix.  C, good luck.

>> In dynamically typed languages
>>a lot of things that can be type errors in static languages simply *cannot*
>>cause errors.  
>I believe that most dynamically typed languages have more flexible type
>systems than most statically typed systems, but I need convincing on the 
>point above.
>....  The same set of errors would occur.  So I do not
>understand why "a lot of things that can be type errors in static languages 
>simply *cannot* cause errors [in a dynamically typed language]".
>

This point is very simple, but perhaps not obvious.  For an example I'll use
the X Toolkit again.

	int width;
	XtVaGetValues(widget, XtNwidth, &width, NULL);

will compile fine and run without giving any error diagnostics.  (For those
not familiar with the X Toolkit, XtVaGetValues is a procedure that takes a
widget object and a varargs list of name, value pairs and retrieves those
properties from the widget.  In order to handle properties of many different
types, the values are type XtPointer which is (usually) caddr_t.  This is a
black hole as far as type checking goes.)  The problem is that the correct
type of an XtNwidth property is Dimension, (which is often) not int.  This
is a type error and C doesn't catch it.  In lisp there is no type error.
The type is latent, stored with width.  If the X Toolkit decided that XtNwidth
should be a bignum there would be *no* changes required to the lisp code.
In the unlikely case that other lisp code makes the erroneous assumption that
width is an int the error will be detected and I'll get an error message.

>one was statically typed and the other dynamically typed.  The dynamically
>typed language would catch all type errors at runtime, presumably with good
>diagnostics about just what variables and types and functions were involved.
>The statically typed system would catch some type errors at compile time.  
>The ones it did not catch would cause difficult to find errors -- at least
>they do in traditional C.  The same set of errors would occur.  So I do not
>understand why "a lot of things that can be type errors in static languages 
>simply *cannot* cause errors [in a dynamically typed language]".
>

See above.  The same set of errors do not occur.  And remember, many difficult
to find errors simply aren't found and the product goes out the door.

-- Doug Quale
quale@saavik.cs.wisc.edu

P.S.  The C compiler won't even give an error diagnostic if you omit the NULL
at the end of of the varargs argument list.  You do get the very handy
"Segmentation fault -- Core dumped" diagnostic when you try to run it.
A language with more flexible and robust argument passing is a lot nicer.

quale@saavik.cs.wisc.edu (Douglas E. Quale) (05/17/91)

In article <1991May17.011209.29486@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>In article <1991May16.153308.4054@spool.cs.wisc.edu> quale@picard.cs.wisc.edu (Douglas E. Quale) writes:
>>In article <1991May16.011804.21042@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>>>[ugly C syntax to do programmer-computed dynamic typing of some X11 values]
>>I think there are reasons why the X Toolkit Intrinsics doesn't do this.
>>One of the design goals was binary compatibility with past versions.
>
>Uh, if you want binary compatibility between existing C code and a
>dynamically-typed language, you'll have a lot of problems.  When we

No, I mean binary compatibility between different C versions of the Toolkit.
Adding new types messes up the tags.  In C the type union approach is awkward
as the X Toolkit resources have a lot of different types.  Unfortunately I
don't have a complete list here, but it includes int, String *, WidgetList,
Function, Cardinal, AcceleratorTable, Pixel, Pixmap, Colormap, Boolean, Screen,
TranslationTable, Dimension, Callback, Position, Visual, Atom, Widget,
InitialState, Window, CallbackList, Cursor, FontStruct*, Justify, ShapeStyle,
Orientation, float, BackingStore, TextPosition, TextResizeMode, TextScrollMode,
TextSelectType*, EditType, AsciiType, and WrapMode.  My apologies to anyone
I've inadvertantly overlooked, and I hope I didn't repeat any types.  These
are only the types of the resources for the Athena widgets, the Motif widget
resources have a *lot* more types, and it must be possible for any widget
writer to add still more.

>
>>Dynamically typed languages are safer than primitive statically typed
>>languages such as C.
>
>No.  Dynamically typed languages are safer than C.  Statically typed
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I believe that's what I said.

-- Doug Quale
quale@saavik.cs.wisc.edu

Primitive statically typed languages are languages that practically force the
programmer to use an unchecked simulation of dynamic typing.  For a start
they generally lack polymorphism, and frequently have little support for
generics at all.  Sadly, a vast majority of the programs written in static
languages are in languages that have very primitive type systems.

cok@islsun.Kodak.COM (David Cok) (05/18/91)

In article <1991May17.045347.26722@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
>In article <1991May16.175340.25522@kodak.kodak.com> cok@islsun.Kodak.COM (David Cok) writes:
>>In article <1991May16.134106.24421@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
>>>For instance, I recently spent more than a couple of minutes figuring out
>>>what was wrong with a C program with this fragment:
>>>
>>>{
>>>	...
>>>	double f, foo;
>>>	int i;
>>>
>>>	...
>>>
>>>	f = modf(foo, &i);
>>>	...
>>>	switch (i) { ... }
>>>}
>>>
>>>The point is, I don't care what numeric type i is.  In a dynamically typed
>>>language this type error would not occur.  
>>
>>It seems to me it still would:  if modf returned for you an i which was a double
>>and the switch statement knew only how to handle int's, you would get a
>>runtime error because of mismatched types.  (If you allow for smarter switch
>>statements or implicit conversion, you've changed the comparison to one of
>>flexibility of the type system rather than static vs. dynamic typing.)
>>
>
>Yes.  I'd get an error _and_an_error_message_ the first time I tried the code.
>C gives me no error message, just the wrong answer.  IMHO the lisp behavior
>is infinitely better in this regard.  Are you actually defending silently
>giving the wrong answer to "Error in switch: expected an int but got a double"
>??????  This bug gets fixed in a dynamic language in the first pass, utterly
>trivially.  What makes you so certain that the programmer would even know
>that the C version was bugged?  No error messages are given.  What if the
>program just happens to give the expected answers on the test cases despite
>the bug?  I'd consider this an overwhelming victory for the dynamically typed
>language.  Guarranteed to find the bug, trivial to fix.  C, good luck.
>
No I am absolutely not defending the idea of  "silently
giving the wrong answer to "Error in switch: expected an int but got a double"'
Read a little more carefully.  C is a bad comparison, as I point out, because
it has so many holes in its type checking.  I was asking for a comparison 
between a dynamically typed language and a strongly statically typed language.
They both would show the error (one a run-time and one at compile-time).  I'm
not advocating one or the other here (and certainly not advocating C) --
just trying to understand the benefits and drawbacks of different systems.

>>> In dynamically typed languages
>>>a lot of things that can be type errors in static languages simply *cannot*
>>>cause errors.  
>>I believe that most dynamically typed languages have more flexible type
>>systems than most statically typed systems, but I need convincing on the 
>>point above.
>>....  The same set of errors would occur.  So I do not
>>understand why "a lot of things that can be type errors in static languages 
>>simply *cannot* cause errors [in a dynamically typed language]".
>>
>
>This point is very simple, but perhaps not obvious.  For an example I'll use
>the X Toolkit again.
>
>	int width;
>	XtVaGetValues(widget, XtNwidth, &width, NULL);
>
>will compile fine and run without giving any error diagnostics.  (For those
>not familiar with the X Toolkit, XtVaGetValues is a procedure that takes a
>widget object and a varargs list of name, value pairs and retrieves those
>properties from the widget.  In order to handle properties of many different
>types, the values are type XtPointer which is (usually) caddr_t.  This is a
>black hole as far as type checking goes.)  The problem is that the correct
>type of an XtNwidth property is Dimension, (which is often) not int.  This
>is a type error and C doesn't catch it.  In lisp there is no type error.
>The type is latent, stored with width.  If the X Toolkit decided that XtNwidth
>should be a bignum there would be *no* changes required to the lisp code.
>In the unlikely case that other lisp code makes the erroneous assumption that
>width is an int the error will be detected and I'll get an error message.
>

Again your example does not fill the bill -- you pick one where the type
checking is turned off, i.e. a weakly typed system.  If you want to argue
that no current statically typed language is flexible enough to do the
right things with variable length argument lists  -- you do not have to 
convince me.  But don't say that you do not get type errors in dynamically
typed languages -- you do; what you don't get are uncaught type errors -- that's
a plus -- at run-time -- that's a minus.

>>one was statically typed and the other dynamically typed.  The dynamically
>>typed language would catch all type errors at runtime, presumably with good
>>diagnostics about just what variables and types and functions were involved.
>>The statically typed system would catch some type errors at compile time.  
>>The ones it did not catch would cause difficult to find errors -- at least
>>they do in traditional C.  The same set of errors would occur.  So I do not
>>understand why "a lot of things that can be type errors in static languages 
>>simply *cannot* cause errors [in a dynamically typed language]".
>>
>
>See above.  The same set of errors do not occur.  And remember, many difficult
>to find errors simply aren't found and the product goes out the door.

The same set of errors do not occur in *C* -- no argument on the fact that C's
type checking is abysmal and type errors go out the door.

>
>-- Doug Quale
>quale@saavik.cs.wisc.edu
>
>P.S.  The C compiler won't even give an error diagnostic if you omit the NULL
>at the end of of the varargs argument list.  You do get the very handy
>"Segmentation fault -- Core dumped" diagnostic when you try to run it.
>A language with more flexible and robust argument passing is a lot nicer.

Agree with the last sentence -- just wondering how to make that language as
statically typed as possible without overly restricting flexibility.

David R. Cok
Eastman Kodak Company
cok@Kodak.COM

quale@khan.cs.wisc.edu (Douglas E. Quale) (05/18/91)

In article <1991May17.221539.22844@kodak.kodak.com> cok@islsun.Kodak.COM (David Cok) writes:
>In article <1991May17.045347.26722@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
>>>> In dynamically typed languages
>>>>a lot of things that can be type errors in static languages simply *cannot*
>>>>cause errors.  
>>>....  The same set of errors would occur.  So I do not
>>>understand why "a lot of things that can be type errors in static languages 
>>>simply *cannot* cause errors [in a dynamically typed language]".
>>>
>>
>>This point is very simple, but perhaps not obvious.  For an example I'll use
>>the X Toolkit again.
>>
>>	int width;
>>	XtVaGetValues(widget, XtNwidth, &width, NULL);
>
>Again your example does not fill the bill -- you pick one where the type
>checking is turned off, i.e. a weakly typed system.  If you want to argue
>that no current statically typed language is flexible enough to do the
>right things with variable length argument lists  -- you do not have to 
>convince me.  But don't say that you do not get type errors in dynamically
>typed languages -- you do; what you don't get are uncaught type errors -- that's

I guess I should have gone a little farther with my example.
I have two widgets, widget1 and widget2.  I want to set widget2's width
to be the same as the width of widget1.

{
	int width;
	XtVaGetValues(widget1, XtNwidth, &width, NULL);
	XtVaSetValues(widget2, XtNwidth, width, NULL);
}

This code is bugged because I used the wrong type for width.  But I really,
really, really don't care what type width is.  In lisp,

	(let ((width (xtgetvalue widget1 xtnwidth)))
	  (xtsetvalue widget2 xtnwidth width))

has no type errors, and can't have any.  Not uncaught type errors,
no type errors, period.

-- Doug Quale
quale@saavik.cs.wisc.edu

diamond@jit533.swstokyo.dec.com (Norman Diamond) (05/20/91)

In article <1991May17.051840.26916@daffy.cs.wisc.edu> quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
>In article <1991May17.011209.29486@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>>In article <1991May16.153308.4054@spool.cs.wisc.edu> quale@picard.cs.wisc.edu (Douglas E. Quale) writes:
>>>Dynamically typed languages are safer than primitive statically typed
>>>languages such as C.
>>
>>No.  Dynamically typed languages are safer than C.  Statically typed
>      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>I believe that's what I said.

It isn't.  Your previous statement confused statically typed languages
with C.  Your example only proved that dynamically typed languages are
safer than one particular collection of C programs.  You didn't even
prove that dynamically typed languages are safer than C in general,
but I made this generalization intuitively.

Now, statically typed languages are also safer than C.  Your same
example (the X-window system), though it does not prove this statement,
remains a valid example.

You play word games in order to create the assertion that dynamically
typed languages are safer than statically typed languages.  If you have
a shred of evidence to support this assertion, it is better to show
your evidence than to play word games.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

chisnall@cosc.canterbury.ac.nz (The Technicolour Throw-up) (05/20/91)

From article <1991May13.061520.11992@daffy.cs.wisc.edu>, by quale@khan.cs.wisc.edu (Douglas E. Quale):
[...]
> This statement suggests that programs compiled in dynamic languages contain
> more type errors than similar programs written in statically typed languages.
> Unfortunately I don't know of any studies that have been made that could
> definitively affirm or deny this.  In fact, I don't know of any evidence at

You could try looking at:

"An experimental evaulation of data type conventions" by J.D. Gannon,
in Communications of the ACM 20 (8), august 1977, pp 584 - 595

which contains the results of a comparison between statically typed and
untyped languages.  Apparently the author had previously looked at the
question of static vs. dynamic typing (but, unfortunately, published it
in some obscure volume that we don't have here :-(. In the preamble to
the above mentioned paper he briefly summarises some of the results of
this prior comparison:

    "... This evidence indicated that the use of dynamically typed
    operands resulted in errors that remain in programs longer than
    the errors attributable to statically typed operands."

The above paper concludes, unsurprisingly, that static is better than
untyped.

I'm not too sure, however, whether his results are applicable to all
languages.  His experiments were performed with variations on algol-like
languages where the variations were in the type system.  I suspect that
some of his results may say just as much about his choice of the underlying
language as about the type systems imposed upon them.

I think that a distinction that it may be useful to draw here is between
declarative languages (e.g. prolog,ML,hope,miranda,smalltalk) which have
a highly modular structure, and non-declarative languages (such as pascal,
fortran,cobol,ada) which tend, imho, to give rise to rather long-winded
programs.  Gannon's results can be seen as a demonstration, then, that
static typing is definitely better for nd languages (which is his under-
lying model).

> Dynamic typing makes program components easier to test interactively in
> isolation; the components get tested again together.  You may say you do

I don't see this at all.  What has typing got to do with testing program
components.  It seems to me that far more important than the type system
is whether the language is declarative (i.e highly modular) or not.
Imagine a version of pascal with dynamic typing - is it easy to test
program components?  Contrast this with declarative languages with static
typing (e.g. ML,hope,miranda,..) - easy to test components? You bet.

> -- Doug Quale
> quale@khan.cs.wisc.edu

--
 "Merely corrobarative detail, intended to give artistic verisimilitude
 to an otherwise bald and unconvincing narrative"    -- W.S. Gilbert 

Name: Michael Chisnall		email: chisnall@cosc.canterbury.ac.nz

rockwell@socrates.umd.edu (Raul Rockwell) (05/20/91)

Douglas E. Quale:
   > This statement suggests that programs compiled in dynamic
   > languages contain more type errors than similar programs written
   > in statically typed languages.  ...

Michael Chisnall:
   [ see previous article for CACM reference and background ]

   I think that a distinction that it may be useful to draw here is
   between declarative languages (e.g.  prolog, ML, hope, miranda,
   smalltalk) which have a highly modular structure, and
   non-declarative languages (such as pascal, fortran, cobol, ada)
   which tend, imho, to give rise to rather long-winded programs.
   Gannon's results can be seen as a demonstration, then, that static
   typing is definitely better for nd languages (which is his under-
   lying model).

Hmm... yes.  The way I remember this group of threads started off with
the assertion that dynamically typed languages were less error prone
than statically typed languages because (paraphrasing slightly)
dynamically typed languages are more declarative in nature.

Maybe the emphasis should have been on declaratively typed languages
vs. non-declaratively typed languages :-)?

Douglas E. Quale:
   > Dynamic typing makes program components easier to test
   > interactively in isolation...


Michael Chisnall:
   I don't see this at all.  What has typing got to do with testing
   program components.  It seems to me that far more important than
   the type system is whether the language is declarative (i.e highly
   modular) or not.  ...

Am I the only one interested in pointing out that an infinite loop is
a type error?  Consider a recent bug I encountered:  a 'continue' inside
an 'if' statement which should have been outside -- without the
continue the code would occasionally fall through to a different state
and would never terminate.  Yeah, that was in C, but testing is the
only real good way to find statements out of order.

Raul Rockwell

sakkinen@jyu.fi (Markku Sakkinen) (05/21/91)

In article <ROCKWELL.91May20081117@socrates.umd.edu> rockwell@socrates.umd.edu (Raul Rockwell) writes:
> ...
>Michael Chisnall:
>   [ see previous article for CACM reference and background ]
>
>   I think that a distinction that it may be useful to draw here is
>   between declarative languages (e.g.  prolog, ML, hope, miranda,
>   smalltalk) which have a highly modular structure, and
>   non-declarative languages (such as pascal, fortran, cobol, ada)
>   ...

BTW, Smalltalk declarative?!
Prolog has a modular structure?!

>Hmm... yes.  The way I remember this group of threads started off with
>the assertion that dynamically typed languages were less error prone
>than statically typed languages because (paraphrasing slightly)
>dynamically typed languages are more declarative in nature.
>
>Maybe the emphasis should have been on declaratively typed languages
>vs. non-declaratively typed languages :-)?

"Started off" at some point of time?  Hasn't it been going on
since time immemorial? :-)  Anyway, it looks like a silly statement
(has anybody really made it?) that having to _declare_ the types
of variables would make a language _less_ declarative.

> ...
>Am I the only one interested in pointing out that an infinite loop is
>a type error?

So it seems:  you have probably insisted on that some 10 times
during the last few months without getting many supporters.
Most people evidently feel (like myself) that lumping too much
into the concept 'type error' would make it too general to be
interestingly different from 'error'.

>  Consider a recent bug I encountered:  a 'continue' inside
>an 'if' statement which should have been outside -- without the
>continue the code would occasionally fall through to a different state
>and would never terminate.  Yeah, that was in C, but testing is the
>only real good way to find statements out of order.

What is the connection of this programming mistake with _type_ errors?
And how does it confirm your opinion that "testing is the only real
good way"?

Markku Sakkinen
Department of Computer Science and Information Systems
University of Jyvaskyla (a's with umlauts)
PL 35
SF-40351 Jyvaskyla (umlauts again)
Finland
          SAKKINEN@FINJYU.bitnet (alternative network address)

strom@watson.ibm.com (Rob Strom) (05/21/91)

In article <1991May17.051840.26916@daffy.cs.wisc.edu>, quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
|> In article <1991May17.011209.29486@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
|> >In article <1991May16.153308.4054@spool.cs.wisc.edu> quale@picard.cs.wisc.edu (Douglas E. Quale) writes:
|> >
|> >>Dynamically typed languages are safer than primitive statically typed
|> >>languages such as C.
|> >
|> >No.  Dynamically typed languages are safer than C.  Statically typed
|>       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|> 
|> I believe that's what I said.
|> 
|> 
|> Primitive statically typed languages are languages that practically force the
|> programmer to use an unchecked simulation of dynamic typing.  For a start
|> they generally lack polymorphism, and frequently have little support for
|> generics at all.  Sadly, a vast majority of the programs written in static
|> languages are in languages that have very primitive type systems.

Let me give you the perspective of someone who is designing and implementing
"better" statically typed languages.

If you want to argue that languages (like C) with incomplete static type
checking and no runtime checking are unsafe, you'll get enthusiastic
agreement from me.  

But if you want to argue that therefore there's something intrinsically
wrong with static typing and that we should use dynamic typing instead,
you'll get enthusiastic disagreement from me.

I agree with you that nonsensical operations should never be executed.
I believe that wherever possible nonsensical operations should be
avoided by static analysis, and where this is not possible, they
should be avoided by runtime checks.  

I have previously posted my opinion that most of the time, it is
reasonable to statically declare the types of values a variable
can hold.  For certain kinds of situations it is not.  That is
why our language makes static the usual case, and dynamic the unusual case,
while allowing both.
-- 
Rob Strom, strom@ibm.com, (914) 784-7641
IBM Research, 30 Saw Mill River Road, P.O. Box 704, Yorktown Heights, NY  10958

quale@saavik.cs.wisc.edu (Douglas E. Quale) (05/21/91)

In article <1991May20.005238.19244@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>>>In article <1991May16.153308.4054@spool.cs.wisc.edu> quale@picard.cs.wisc.edu (Douglas E. Quale) writes:
>>>>Dynamically typed languages are safer than primitive statically typed
>>>>languages such as C.
>>>
>>>No.  Dynamically typed languages are safer than C.  Statically typed
>>      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>I believe that's what I said.
>
>It isn't.  Your previous statement confused statically typed languages
>with C.  Your example only proved that dynamically typed languages are
>safer than one particular collection of C programs.  You didn't even
>prove that dynamically typed languages are safer than C in general,
>but I made this generalization intuitively.
>
>You play word games in order to create the assertion that dynamically
>typed languages are safer than statically typed languages.  If you have
>a shred of evidence to support this assertion, it is better to show
>your evidence than to play word games.
>--

No.  I don't confuse statically typed languages with C.  I may confuse C
with a primitive statically typed language, but I don't think that's a
confusion.

Dynamically typed languages are safer than primitive statically typed
languages such as C, exactly as I said.  I should rather have said languages
with primitive static typing, but my original statement is close enough.

In primitive static typing systems type safety is thrown out the window to
provide genericity.  You can disagree with me, but this is not a word game.

SML has a much better type system than C, but I'm not certain how convenient
it would be for writing X programs.

-- Doug Quale
quale@saavik.cs.wisc.edu

rockwell@socrates.umd.edu (Raul Rockwell) (05/22/91)

Michael Chisnall:
   >   I think that a distinction that it may be useful to draw here
   >   is between declarative languages (e.g.  prolog, ML, hope,
   >   miranda, smalltalk) which have a highly modular structure, and
   >   non-declarative languages (such as pascal, fortran, cobol, ada)

Markku Sakkinen:
   BTW, Smalltalk declarative?!  Prolog has a modular structure?!

heh.  In the smalltalk group you've got languages which can declare
data to be some type.  In the pascal group you've got languages where
you declare variables to be some type and data is typed as a side
effect and you must handle type information with control flow (with
exceptions for language intrinsics).  The above grouping doesn't bear
too close examination however...

Markku Sakkinen:
   it looks like a silly statement (has anybody really made it?) that
   having to _declare_ the types of variables would make a language
   _less_ declarative.

Well, the idea is that you can't declare the type of a piece of data,
and must compensate by using some other mechanism to keep track of
this state information.

Me:
   >Am I the only one interested in pointing out that an infinite loop
   >is a type error?

Markku Sakkinen:
   So it seems: you have probably insisted on that some 10 times
   during the last few months without getting many supporters.  Most
   people evidently feel (like myself) that lumping too much into the
   concept 'type error' would make it too general to be interestingly
   different from 'error'.

Well, in the context of turing machines, the definition of a type
error is a combination of an algorithm and data which causes an
infinite loop.  But you're right, infinite loops are too general for
them all to be called type errors.

   >  Consider a recent bug I encountered:  ...

   What is the connection of this programming mistake with _type_
   errors?  And how does it confirm your opinion that "testing is the
   only real good way"?

Not "only real good way" but still essential.  Essential does not mean
that other techniques are not useful.

About the bug: (1) it appeared as an infinite loop which occurred only
for certain input values.  (2) it is possible to write that particular
algorithm (a string matching problem) without using loops.  (3) in C,
I had to represent some of the information as program state and write
loops, so this was a data representation problem.

I suppose I'm coming across as rather unreal, but I can't help it :-)
I rarely use loops or conditional expressions in my own code because I
rarely need to.  Control flow is just another way to represent data.

Raul Rockwell

quale@saavik.cs.wisc.edu (Douglas E. Quale) (05/22/91)

>|> >In article <1991May16.153308.4054@spool.cs.wisc.edu> quale@picard.cs.wisc.edu (Douglas E. Quale) writes:
>|> >
>|> >>Dynamically typed languages are safer than primitive statically typed
>|> >>languages such as C.
>|> >

I just realized that perhaps my use of the word primitive was taken as a
perjorative aimed at all statically typed languages, rather than only
statically typed languages with particularly poor type systems such as C as
I had intended.

About a year ago, I wrote a short nqueens function in Scheme

(define (nqueens n)
  (letrec ((try-col (lambda (c b)
		      (if (= c 0)
			  b
			  (try-row n c b))))
	   (try-row (lambda (r c b)
		      (cond ((= r 0) '())
			    ((safe? r b) (append (try-col (- c 1) (cons r b))
						 (try-row (- r 1) c b)))
			    (else (try-row (- r 1) c b)))))
	   (safe? (lambda (r b)
		    (let loop ((up (+ r 1))
			       (dn (- r 1))
			       (bd b))
			   (or (null? bd)
			       (and (not (= (car bd) r))
				    (not (= (car bd) up))
				    (not (= (car bd) dn))
				    (loop (+ up 1) (- dn 1) (cdr bd))))))))
	(try-col n '())))

A simple test,

> (nqueens 4)
(2 4 1 3 3 1 4 2)

and I see I made a type error.  Looking at the source it was trivial to
fix, but it occurred to me that the SML compiler would have rejected the
program immediately.  This shows that some programmers (namely me) can make
elementary type errors even in very, very simple programs.  Unfortunately
it's so trivial it doesn't show much else.

I looked up the CACM reference given re: type errors in statically vs
dynamically typed languages.  Unfortunately the experiment really dealt
only with an untyped language.  The only untyped languaged that I've used
is assembly language.  Bliss and BCPL are still in use, but in general I
wouldn't think that untyped languages have much to recommend them.  I still
have to treat the assertion that "programs in dynamically typed languages
have more type errors than those in statically typed languages" as having
no objective evidence either way.  (Remember, statically typed languages
give many more chances to make type errors.  Some programs with type errors
in a statically typed language cannot have type errors in a dynamically
typed language.)

Static typing brings up the problem of type equivalence:  should the
language use name equivalence or should it use structural equivalence?
This question got a lot of attention in Pascal, but I don't know that the C
community has given it thought.  C uses structural equivalence which can be
less than helpful, especially when a large program typedefs dozens of
different things to int.  As an example from X Windows again, Xlib typedefs
XID as unsigned long.  Window ids are XIDs, so the call

	XDestroyWindow(display, 2 + 2);

is accepted by the compiler even though this is really a type error.
Although this is rather unlikely, pixels in Xlib are also unsigned longs so

	XDestroyWindow(display, pixel);

is another type error that can't be caught.  In order to catch these errors
using structural equivalence XID would have to become a struct, and that is
a somewhat unpleasant arrangement.  In SML we could simply write

datatype Window = Win of int

fun XDestroyWindow (Display dpy) (Win win) = ....

and in fact although Window is a structure, the compiler doesn't need to
tag it so it gives the same efficiency as an int but is much safer.  You
can also greatly increase type safety --

datatype voltage = Volt of real
datatype current = Amp of real
datatype resistance = Ohm of real

fun ohms_law (Amp i) (Ohm r) = (Volt i * r)

(Pattern matching is great -- inside the function ohms_law we can treat i
and r as reals and use ordinary multiplication.  To the outside world they
look like structures.)

This is a big win for sophisticated static typing.  Dynamic typing can do
this, but it's slow and painful.  The types would have to be explicitly
tagged, untagging them before performing arithmetic etc.

Static + dynamic typing in the same language might overcome any problem.
Suppose however, that only static typing is supported.  How does Ada or SML
handle the resource problem in the X Toolkit?  It must be possible for a
widget writer to add arbitrary types to his widgets, and not have to
recompile libXt.a, the X Toolkit library.  The C implementation simply uses
unchecked dynamic typing.  This is much worse than using a language that
supports dynamic typing because no type checks are performed even at run
time.  Is there a better way?

-- Doug Quale
quale@saavik.cs.wisc.edu

doug@netcom.COM (Doug Merritt) (05/23/91)

In article <1991May20.172441.780@csc.canterbury.ac.nz> chisnall@cosc.canterbury.ac.nz writes:
>From article <1991May13.061520.11992@daffy.cs.wisc.edu>, by quale@khan.cs.wisc.edu (Douglas E. Quale):
>[...]
>> This statement suggests that programs compiled in dynamic languages contain
>> more type errors than similar programs written in statically typed languages.
>> Unfortunately I don't know of any studies that have been made that could
>> definitively affirm or deny this.  In fact, I don't know of any evidence at
>
>    "... This evidence indicated that the use of dynamically typed
>    operands resulted in errors that remain in programs longer than
>    the errors attributable to statically typed operands."

This is in fact trivially true. Errors caught at compile time are
guaranteed to be 100% detectable (and removable), whereas errors caught
at run time cannot be detected until just the right conditions occur,
so in arbitrary programs it will take arbitrarily long for all run time
errors to occur and be detected. Or even infinitely long, since proving
otherwise is the halting problem.

Therefore dynamically typed languages are inheritantly less safe than
strongly statically typed languages, because only in the latter can you
know that all type errors have been removed.

This is a minor point, though, because there are situations where dynamic
typing is a powerfully expressive and natural tool, and the desirability of 
such is (in some situations) far more important than merely increasing the
safety of type usage.

The reason why that is true is that if you really need dynamic typing,
but the language doesn't support it, then you have to implement it yourself
anyway (that's what e.g. C unions and Pascal variant records are *for*,
after all), and now you've written new code that may contain errors,
so you haven't really gained anything.

Note that this argument is algorithm-specific, and says nothing in support
of completely dynamically-typed languages over optionally dynamically-typed
languages.

BTW there's also an age-old esthetic criterion that "everything should be
a first class citizen", and it derives from the practical experience of
awkwardness of expression that results for certain applications if some
things are second class citizens. This is a somewhat stronger argument
than simply "dynamic typing"; it argues for dynamic typing of the strongest
sort, that allows type-values to manipulated via a calculus (ideally
via an algebra).

All in all, one really wants dynamic typing allowed, but optimized out
and statically checked where at all possible. This is a challenge for
language design (I'm working on it :-)
	Doug
-- 
Doug Merritt	doug@netcom.com		apple!netcom!doug

strom@watson.ibm.com (Rob Strom) (05/23/91)

In article <1991May22.161814.15196@daffy.cs.wisc.edu>, quale@saavik.cs.wisc.edu (Douglas E. Quale) writes:
 
|> Static + dynamic typing in the same language might overcome any problem.
|> Suppose however, that only static typing is supported.  How does Ada or SML
|> handle the resource problem in the X Toolkit?  It must be possible for a
|> widget writer to add arbitrary types to his widgets, and not have to
|> recompile libXt.a, the X Toolkit library.  The C implementation simply uses
|> unchecked dynamic typing.  This is much worse than using a language that
|> supports dynamic typing because no type checks are performed even at run
|> time.  Is there a better way?
|>
Hermes uses "polymorphs".  You apply the "wrap" operator to a value of any
data type.  The result is a value of type "polymorph", which can be stored
in a variable of type "polymorph".  It can be copied, stored, and passed
around, but no type-specific operations can be applied.  You must then
"unwrap" the polymorph into a variable of type T before applying operations
appropriate to type T.  A runtime check is made that the wrapped polymorph
value actually is of type T.

This allows dynamic typing where needed, while retaining static typing as
the more common situation.  Whether checked statically or dynamically,
type safety (plus "typestate safety" --- e.g., avoiding reading undefined data)
is always assured.
 
-- 
Rob Strom, strom@watson.ibm.com, (914) 784-7641
IBM Research, 30 Saw Mill River Road, P.O. Box 704, Yorktown Heights, NY  10598