Trends in language syntax

Who said I wasn't fond of Delphi? Look: Delphi is a great tool. I wish absolutely nothing but the best for DevCo and the Delphi development community.

[However... ]

I have yet to hear an argument that makes me think that the Delphi language is going to experience a rennaissance in popularity that will make it anywhere near as influential as, say, Turbo Pascal.

A correspondent who tells me that C# is more a descendant of Delphi than C++ argues my point for me. Let's take a look at how Anders Hejlsberg's languages have differed from their immediate predecessors:

  • Turbo Pascal : IDE
  • Delphi : Visual builders, components
  • J++ : C-style syntax, delegates, declarative interop
  • C# 1.0 : attribute metadata, Common Language Runtime, relaxed exception specificity (no checked exceptions)
  • C# 2.0 : generics, partial classes, anonymous delegates
  • C# 3.0 : type inference, relational operators including projection and selection (i.e.,dynamic classes),¬†full closures, extension methods

So if you were to say "trends in Anders Hejlsberg's work," I think it would certainly be fair to say that, aside from the obvious switch to a C-style syntax, you also see a trend away from Niklaus Wirth's philosophy of an explicit nested structuring of programmatic components. It's absolutely true that Microsoft's imprimatur is a major part of C#'s popularity, but let's also give credit to Anders Hejlsberg for having a pretty darn good sense of the market (as both a reflection of what is needed and as a thought-leader in advocating what he believes).

Two more examples of the trend away from structural explicitness: In C# 3.0, there are extension methods, which allow an instance method to be specified independently of the file(s) in which the class was originally declared. For instance, static void Foo(this String s){ ? body ? } makes it possible to call Foo() from all instances of type String (in other words, string s = "hello"; s.Foo(); becomes legal code).

Similarly, here's a simple class in Ruby:

Simple enough, right? Class Foo has instance variable \@bar that's assigned in method Baz(). But because Ruby has syntax to indicate that a symbol is an instance variable (the @ prefix), the above class can be equivalently declared as:

class Foo
def Baz(x)

Why is an explicit declaration of instance variables necessary? The instance variable \@bar is part of the programmatic structure that is Foo, but it's declaration (to the extent that it has one at all) is in implicit in the use of that instance variable within methods.

Now, let's talk about files. In the days when C and Turbo Pascal were very influential, there was a close correspondence between a compilation unit, a file, and programmatic components. The matching up of symbolic names between compilation units was a big deal ? in the world of C, this link stage is often the lengthiest stage. The associated language syntax actively worked against the design-time experience of the programmer, since the programmer has a very dynamic set of interests that span multiple (what today we'd call) namespaces. You still see remnants of this in IDEs today: a parser used to provide Intellisense / code completion is much more complex and fragile than a parser used to generate code (the Intellisense parsers in Visual Studio 2005 seem to be a primary source of bugs reported for that product).

The correspondence between files, compilation units, and programmatic components made a lot of sense in the days before capacious hard-drives and RAM. Nowadays, the correspondence makes far less sense: we can keep windows open with however many buffers we need (buffers? Hah! Not only do I date myself, I show how the file / RAM false dichotomy still part of me). When we search for a symbol, we expect the IDE to resolve across files and namespaces. The main justification for files today is as units of source control!

Templates / generics and components (especially GUI-related) cracked, within the mainstream, the file-compilation unit-programmatic component correspondence. GUI builders inherently provide a design-time view of structures under construction. We increasingly expect the same type of design-time access to data, XML representations, object graphs, etc.

Why would anyone think that this trend towards increasing design-time views of programmatic components will stop at the class boundary? Surely mainstream languages will evolve to have an increasingly blurry distinction between design-time and run-time programatic structures.

Smalltalk-80 (as in 1980, mind you) anticipated all of this.

Put aside the Smalltalk syntax and just look at this browser (well, it's Squeak, but it's the first image returned by Google). The panes along the top are, I think, self-explanatory and the pane at the bottom is the pane in which you edit. Note the absence of a "project view" or a file / class correspondence. Are they missed? Only a little, in that your classes and code can have a tendency to disappear into the forest of library functions. But in general, this browser remains a view of the mainstream future.

The other relevant aspect of Smalltalk's model is the non-distinction between program construction and execution. In Smalltalk, the view of your program (whether as part of construction or delivered to the customer) is not necessarily built from first principles when you run a program. During program construction, this means that you can shut things down in the middle of debugging and return at a later date to the exact same situation. When the program is deployed, it means that there's much more flexibility about how to approach issues like customization.

Any edits to classes made in one view will propagate automatically to other views, not due to machinations of a separate IDE, but due to the fact that the IDE is part of the image in which you are working (you have the flexibility to strip down the image for deployment, if desired).

Darn it, I can't find a picture that communicates how the Workspace / Image work. Perhaps a Smalltalker can offer something in the comments?.

Although a solid argument can be made that Smalltalk (and Lisp, as well) may enjoy a rennaissance based on these types of structural advantages ("Smalltalk is the next big thing: always has been, always will be"), I want to move on away from languages entirely and talk about two really important trends that will, undoubtedly, influence future language design: unit testing and concurrence.

A major argument of those who favor implicitly-typed languages is that "unit testing replaces type information," that double SquareRoot(uint i){ ? } has no advantages over def SquareRoot(i){ ? } so long as the compilation process includes executing something along the lines of { i = -1; SquareRoot(i) ? } and that execution results in the appropriate condition (whether that's returning NaN or throwing an exception or whatever).

Today, unit tests are invariably developed as components external to the class being tested. The existence or non-existence of a unit test is not reflected in the tested class. The obvious problem is that possibility of absence: not only are non-comprehensive test suites a possibility, it takes considerable effort to ensure the existence of an even trivially comprehensive test suite (simple coverage, much less comprehensive coverage of corner cases). It is inevitable that there will rise a metadata-based connection between unit tests and classes under test. I can imagine a language that looks something like:

[Fit(pre = { i = 0}, post = { result = 0 })]
 [Fit(pre = { i = 4}, post = { result = 2 })]
 [Fit(pre = { i = -1}, post = { throws ArgumentException} )]
 def SquareRoot(i) { ? }

Now, my syntax just violated the trend away from structural explicitness, so maybe it would be, instead: Fit(Library.SquareRoot, pre = { i = 0}, post = { result = 0 }), but the upshot would be that the method Library.SquareRoot would always carry the association of its preconditions, postconditions, and invariants. The Eiffel language already has this design-by-contract metadata association, although it doesn't (I believe) support Fit-style pre-post value pairings.

[I find it amusing when implicit typing / unit-testing advocates say explicit typing doesn't have benefits. What are unit tests but explicit constraints on the behavior and range of variables? Unit tests are type information. Very detailed, very domain-specific type information. Implicit typers often try to have it both ways: praising in one breath for the speed of implicit typing and then speaking of the confidence resulting from a "green bar" comprehensive test suite, but those are two diametrically opposed different development scenarios. Developing a comprehensive test suite in an implicitly typed language is faster than developing such a suite in an explicitly typed language, but a thorough test suite takes longer than "finger-typing" explicit type information. (I think there's a happy medium in a test suite that is comprehensive on publicly visible components and not necessarily so with internally visible components. This is why I hesitate to advocate test-driven development.)

On to concurrence. The coming era of manycore machines is going to hit us like a tsunami. The major impediment to the historical success of Lisp and Smalltalk was relative performance. I'm not at all saying that Lisp and Smalltalk couldn't be "fast enough" for their programmers, but they always faced scenarios where they consumed many times the resources of code written in lower-level languages (Ruby today faces the same problem: it will be interesting to see if enough Moore's generations have passed so no one notices). In the future, when we get past 2 or 4 cores, performance will be dependent on concurrency abstractions that must be in syntax. You can't library your way out (well, you can, but only in the sense that you need a library plus you have to not do a bunch of things that are in your language. If you want to know how successful that type of approach is, talk to someone who knows the history of J2EE).

I don't have a strong opinion about the form of the concurrency abstractions that will succeed, but I guarantee you that by 2016, any language that doesn't have such abstractions will not be considered professional quality.

For the past 18 months, during which I've been writing quite a few columns on trends in language syntax, I've been expecting someone to challenge me to explain the state of JavaScript (yeah, yeah: ECMAScript. Blech.): a C-derived syntax, implicit typing, a flexible object model, Web aware, and essentially universally deployed. By my logic, JavaScript should be much more popular than it is. I gotta' admit, it's a head scratcher. Sure, there's not a great JavaScript IDE, but to me that's a cart-before-the-horse thing: if a lot of people were slavering to code JavaScript, a good IDE would have emerged by now.

Further, JavaScript is the language for Flash and, aside from Macromedia's incompetent marketing, why Flash doesn't absolutely own the professional "rich Internet application" market is utterly beyond me. Which touches on AJAX. If I were in a debating club, I could say "JavaScript is successful, it's the language of AJAX, and AJAX is the cool new thing."

But I don't think that's the truth, I don't think you can look at JavaScript and say, "yeah, in the world of professional programming, that's a tool that people embrace." I think people kind of begrudgingly say "Yeah, okay, if we need to do that in the browser I'll do it in JavaScript," and then they sigh and check the NBA finals (hey, the Larry O'Brien Trophy!).

Is it the lack of an IDE? The association of JavaScript with the browser and the resulting ugliness of all that \<script> tag, single-quote / double-quote stuff? The libraries? The lack of marketing?

Hey, it's a blog entry. I don't have to come to any kind of conclusion.