At 07:56 PM 11/11/98 , Bill Frantz wrote:
>Since one of the design goals of E is to be useful for rapid prototyping
>environments, we should examine it's feature with that in mind. I think it
>comes off fairly well.
>One important feature of a rapid prototyping language is that things you
>write are not likely to have hidden bugs that only trip you up much later
>[-] Dynamic type checking (vs. static)
[-] The type checking issue cuts both ways.
While the point you make is correct -- static checking catches many errors earlier -- the empirical result in the marketplace is that languages called "rapid prototyping languages" are only dynamically typed: Perl, Python, Tcl, all Lisps & Scheme, Smalltalk, Self, Script-X, various shells, Visual Basic, Hypertalk, AppleScript, and expert system shells. Personally, I know of no exceptions to this (but I don't know about REXX. ??).
Enough people have promoted a good enough range of well designed static type systems that it's probably not that everyone is confused, so how should we make sense of this discrepancy? Let's start with similarities between the software development process and garbage collection.
Modern garbage collection starts with the observation, by Hewitt & Lieberman in the '70s, that objects have a high infant mortality. If an object is very young, chances are it's garbage by the first time you check. The small fraction of objects that survive several collection attempts will probably survive the next one. The general prescription that follows is to segment objects by lifetimes, because the appropriate investment strategy differs. Spend more time collecting infants in order to spend less space. Spend less time collecting elders, even though you'll then spend somewhat more space.
Similarly, code has a high infant mortality. Or at least, *it should*. Rapid prototyping can be understood as supporting the writing, and rapid disposal, of high infant mortality code. Some people (like myself) often work out their thoughts by thinking aloud, and are sometimes misunderstood by those who think before they speak.
Similarly, some people (like myself) often work out their thoughts "thinking by coding", and are sometimes misunderstood by those who always think before they code. Most of these thoughts-in-code don't survive their first run. In strongly typed languages, I have to first invest in all sorts of static correctness before I can try out my idea and realize it was garbage anyway. Static checking at this stage makes it *harder* to realize a program is bad.
The small fraction of programs that survive these initial trial-runs will probably be around for a while, so it's now worth a bigger investment to ensure their correctness. At this stage, static correctness checkers of all sorts are an asset.
By "rapid prototyping", I mean the first of these stages. How does this compare with y'all's impressions of how the term is used?
Separation of Concerns: ELint
Though E makes the tradeoff towards thinking-by-coding, I believe external static checkers/inferencers can be straightforwardly written for E (and in E). There is no reason for the E language to reject programs that fail to pass such static checks, but if a given shop wants to enforce these rules for their own programs, they could run such an ELint from a cvs-checkin script (much as EC banishes tab characters from its source code with such a script). Even a shop that so enforces exactly the rules a statically typed language would have banished still benefits from this separation -- if their developers were using a statically typed language, they wouldn't be able to think-by-coding as well *before* checking in.
Also, of course, there can be as many ELints as there are type theories (and other static correctness theories) one might want to use to analyze E code, but without forking the E language.