From Sun Apr  6 06:48:38 1997
Date: 6 Apr 1997 06:13:46 GMT
From: John Ousterhout 
Subject: Re: Ousterhout and Tcl lost the plot with latest paper

Wow, there's been quite a party going on over here on comp.lang.scheme!
I'd like to respond to a few of the comments about my white paper on
scripting, but first a couple of introductory remarks:

1. The paper is not intended to be a complete taxonomy of all programming
   languages nor is it intended to discuss every factor that contributes
   to the usefulness of a language.  The paper has a very narrow focus,
   namely to explain what scripting is and why it's important.  I
   intentionally limited the discussion to a few issues such as system
   programming vs. scripting, components vs. glue, and strongly typed
   vs. untyped.  Of course there are other issues in programming language
   design.  At the same time, I think that the issues in the paper explain
   a lot about what's going on in real-world programming.

2. Many people objected to the fact that their favorite programming
   was left out of the white paper.  Yes, I have heard of Scheme,
   Smalltalk, ML, etc.  I left these languages out because they
   didn't seem particularly relevant for the discussion.  No offense

3. It's very hard to settle arguments about programming languages
   because it's hard to produce meaningful quantitative evidence about
   things like programmer productivity.  I tried to illustrate my points
   with historical examples and a few quantitative anecdotes, but I
   admit that these are soft.  I'd be delighted to see better
   quantitative evidence either supporting or contradicting my
   arguments.  For example, if you know of any quantitative measurements
   of productivity improvements caused by object-oriented programming,
   please let me know.

When Alaric Williams told me about the flame-fest on comp.lang.scheme,
he proposed a set of counter-arguments for me to respond to.  Here
they are, along with my responses.

     - Typlessness, as evident in TCL, is not necessarily the best solution.
    Dynamic typing is generally agreed to be far more powerful and safe.

Actually, I think Tcl is dynamically typed: everything is checked
at runtime for at least syntactic validity.  I used a slightly offbeat
definition of "typing" in the paper: by my definition, "typing" means
declaring the nature of something in advance in order to restrict its
usage.  You would probably call this "static typing", no?

     - TCL does not scale well to large systems; it is fine for small
    "glueing" applications, but in the "real world", such applications
    are expected to grow with time, and soon proper typing becomes
    necessary, more efficiency becomes necessary, etc.

When I started on Tcl I thought this would be true, but in fact many
people have built surprisingly large programs in Tcl.  For example,
there is a real-time Tcl application containing several hundred thousand
lines of code that controls a $5 billion oil well platform and (much to
my shock) it seems to be quite maintainable.  Sybase has something like
a million lines of Tcl code in their test suite.

I think it depends a lot on the application.  The oil well application
actually subdivides into a whole bunch of small tasks, so it's really
more like 500 smaller programs.  Also, if the application is
fundamentally gluing (i.e. the complexity is in the interconnections)
then switching to a more strongly typed language will just make things
worse.  One final argument: suppose that Tcl code is harder to maintain,
line for line, than code in a more strongly typed language (I suspect
this is true).  But if a Tcl application has only 1/5 or 1/10 the lines
of code of the equivalent program in a strongly typed language, it may
still be easier to maintain overall.

That said, I still suspect that as scripting applications grow it makes
more and more sense to implement parts of them in a system programming
language.  The great thing about scripting languages is that this is
easy to do.  You can take the performance-critical kernel of a Tcl
application and implement it in C or C++; ditto for any complicated data
structures or algorithms.  The simple, non-performance-critical parts
can be left in Tcl.  I knew when I started on Tcl that it wouldn't be
appropriate for all problems, so I designed it to work smoothly with
other languages.  In contrast, most languages are egotistical: they
expect you to do *everything* in that language and make it very hard to
split the functionality of an application between multiple languages.
For example, I've been involved with several attempts to make C and Lisp
work together, and they all failed.

     - It is possible to make languages with execution speeds like C or C++,
    that use dynamic typing successfully, whilst being high-level enough
    in the creation of abstractions to "glue" things together quite
    nicely and easily.

Can you point to a specific language and identify a large community of
users who agree with this assessment?   Many people have made claims like
this to me, but no one has been able to point to a good real-world
example.  The white paper argues that you can't have a jack-of-all-trades
language.  Either you have a strongly typed language, which gives high
speed and manageability but makes gluing hard, or you have a weakly
typed language with the opposite properties.
     - Do you really think that object orientation has failed? C++ is a bad
    language, indeed, but what about Self, Java, and other such OO success
    stories from... Sun Labs? Do I detect interdepartmental rivalry?

I overstated the arguments against OO programming in the paper and I'll
probably soften them a bit in the next draft.  I actually think that
there are some good aspects of OO programming, and I use them myself
even when I'm not programming in an OO language.  But I stand by the two
main points in the paper, which are that (a) OO programming hasn't
increased productivity dramatically because it doesn't raise the level of
programming significantly (it may improve things 20-30%, but I doubt
there's even a factor of 2, let alone 10) and (b) implementation
inheritance really truly is a bad idea that tends to reduce reuse and
productivity.  I think you'll see substantial support for the second
claim even among OO enthusiasts.

As for Java, it's hard not to be envious of its success (aren't you
guys a bit envious too?), but Tcl is really symbiotic with Java, just
as Tcl is symbiotic with C.  I look on Java as a better system
programming language that's particularly well-suited for creating
portable Internet components.  Tcl is moving to the Internet itself,
and C isn't a good component language in that domain, so I'm delighted
to have Java around for implementing Internet components that Tcl
can then glue together.

By the time I found out about the discussion on comp.lang.scheme my news
server had already flushed some of the earlier articles, so I've missed
some of the arguments.  I trolled the articles that were left for
comments to discuss, but didn't find a lot.  Most of the articles seemed
to be discussing my motives and ancestors more than the ideas in the
paper;  I'm not sure how to respond to a comment such as "he obviously
doesn't have a clue" except by saying "Hmmm, let me see... wait ...
here's one in my wallet!  Whew..."  You guys seem to have more
ad-hominem arguments than we do on comp.lang.tcl.

However, I did find a few comments that I'd like to respond to; here
they are (indented), along with my responses:

    > I have only skimmed the article so far, but one thing struck me
    > immediately.  At one point he gives an "anecdotal" table where
    > something is programmed originally in C or C++, at enormous expense
    > in programmer hours, and then re-implemented in Tcl/Perl/whatever
    > in ten or fifteen minutes. It would be interesting to see if the
    > same skew existed for programs that were written in scripting
    > languages (or for that matter, Lisp or Scheme or Python) first,
    > and then re-implemented in C or C++. It's hard to believe the ratios
    > would be as large.

Look carefully at the "Comments" column in the table: some of the
applications were written in C/C++ first, while others were written in
Tcl/Perl first.  Indeed, scripting appears to have less benefit in the
cases where the scripting implementation was first.  I believe the
caption in the table mentions this, and the 5-10x advantage I claimed
for scripting is the middle range of the table to try to compensate
for learning effects in the second implementation.

    His arguments on "typeless" languages is useless.
    You don't need a "scripting language" to
    get usable abstractions without the need
    to deal with low-level issues.
    button .b -text Hello! -font {Times 16} -command {puts hello}
    In Macintosh Common Lisp I'll write this as:
    (make-instance 'button-dialog-item
      :dialog-item-text "Hello"
      :view-font '("Times" 16)
      :dialog-item-action (lambda (item) (print "hello")))

I think this example supports my claim that scripting languages are a
lot easier to use when you need to mix and match lots of things of
different types.  The MCL example is a lot more verbose and complicated
than the Tcl example.

    He also gets confused when he talks about object oriented programming
    being a failure. He attributes the short comings of one implementation
    (C++) to the whole approach, much like people who reject Lisp/Scheme
    because of one particular implementation.

Time will tell on this issue.  Personally I think that the problems with
OO programming go beyond just C++.

    >The button example requires about 25 lines of code in three procedures
    >when implemented in C++ with Microsoft Foundation Classes. Just
    >setting the font requires 7 lines of code:
    >LOGFONT lf;
    >memset(&lf, 0, sizeof(lf));
    >lf.lfHeight = -16;
    >strcpy(lf.lfFaceName, "Times New Roman");
    >CFont *fontPtr = new CFont();
    Come on! All this shows is the inconveniece of using the MFC
    classes. An interface exactly the same as the Tcl one could easily be
    written in C++.

I invite anyone who believes this to try to do it, and post the results.
I've had this argument before, and when people do this, one of two things
happens: either they eventually concede that this is hard to do in C++, or
they define new C++ APIs that are essentially untyped (e.g. they use
strings for everything).  This just supports my arguments that types get
in the way of gluing.  You can build untyped APIs in strongly typed
languages, but they tend to be clumsy because the languages are designed
to encourage strong typing.  If you need an untyped approach, you might
as well use a language designed for that.

    > >The button example requires about 25 lines of code in three procedures
    > >when implemented in C++ with Microsoft Foundation Classes. Just
    > >setting the font requires 7 lines of code:
    > >
    > >LOGFONT lf;
    > >
    > >memset(&lf, 0, sizeof(lf));
    > >
    > >lf.lfHeight = -16;
    > >
    > >strcpy(lf.lfFaceName, "Times New Roman");
    > >
    > >CFont *fontPtr = new CFont();
    > >
    > >fontPtr->CreateFontIndirect(&lf);
    > >
    > >buttonPtr->SetFont(fontPtr);
    CButton* button1;
    CButton* button2;
    button1 = new CButton();
    button1->Create("Push me", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, r, this,
    button2 = new CButton();
    button2->Create("Pull you", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, r, this,
    font = new CFont;
    Basically 3 lines to create a font (reusable assuming you only 
    what a few types of fonts, set up a function to handle size changes
    if it's the same, you can also create a simple function to handle
    defaults for everything but the size and type.
    3 lines to create a Button.
    I don't know where Oesterhout's reference on MFC comes from
    (I'm just looking at Brain & Lovette's book).

I'm not an MFC expert, so I asked someone else, whom I consider to be
a good Windows programmer, to write this for me.  Perhaps there is a
shorter way than the code I included.  However, the 6 lines above
don't seem to be equivalent to the Tcl script.  For example, there is
no code to respond to the button press, and I believe additional code is
needed to free resources when the button is deleted.  Suppose that the
MFC code I used is off by a factor of two, and that it really only takes
12 lines of C++ to duplicate the functionality of one line of Tcl.  Doesn't
that still illustrate my point?