From ouster@tcl.eng.sun.com Sun Apr 6 06:48:38 1997 Date: 6 Apr 1997 06:13:46 GMT From: John OusterhoutTo: python-list@cwi.nl 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 intended... 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 OO 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(); > >fontPtr->CreateFontIndirect(&lf); > >buttonPtr->SetFont(fontPtr); 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, 101) button2 = new CButton(); button2->Create("Pull you", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, r, this, 102) font = new CFont; font->CreateFont(16,0,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,"times"); button1->SetFont(font) button2->SetFont(font) 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?