The Land of the Terminal

A Cautionary Tale

An essay I wrote involving the use of text in programming languages. The fact that subtext was just recently mentioned here is actually a coincidence, but I'll take it.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Well, if you want 1.5-dimensionality,

there's Python and Haskell; and if you want true 2-dimensionality, there is Befunge.

not exactly

Not exactly the "2d" I was talking about ;-) Just because you're using a richer interface doesn't mean the underlying data has to change.

A couple of thoughts

None of these are intended as Reasons Why Programming Languages Should be Text, but instead why GUI-based languages probably meet resistance.

* Text, for all its warts, is highly portable--and the main "trouble areas" for porting text across systems (raw ASCII vs UTF8 vs UTF16 vs something else; CR/LF issues) are generally easily worked around. Only in recent years are we starting to see GUI implementations that a) are portable, b) look nice, and c) have adequate performance.

* PL researchers learn techniques for text processing (parsing and scanning) as an introductory part of the discipline. PL researchers are the last people you want designing a GUI. :)

* Naming. In programming, there are many times that you reference something by name. In many cases, the number of choices is gigantic--use of a GUI widget to select a name is impractical in this case, so you gotta take your hands off the mouse and move 'em to the keyboard. (OTOH, use of a GUI can eliminate one common use of names--to permit multiple use of a local term).

And reasons it might change...

* Lots of people do do graphical programming anyways--IT programmers have been dragging controls onto forms for years. Some do it without knowing they are programming.

* XML and other things make it easier to represent programs-as-graphs in a textual format.

* Many problem domains use notation (language) which is graphical in nature--maths notation has been oft-discussed here. Music is another.

* Cross-platform GUIs are getting better. Web apps are ubiquitous.

What will probably happen is that graphical means of specification will continue to increase in prevalence--but we probably won't ever see a programming language that doesn't require some means of inputting text. Much as GUIs are commonly used for common file manipulation operations, but modern OS's still keep a shell around...


Yup, that basically sums up the arguments for both sides. Although, in regards to your "naming" point, I'm not advocating the abolishment of all text from programming. But you should only really need it when you're naming stuff, and even then you should only have to if you want to. A great example of the latter would be do-notation in haskell:

do_something_possibly :: X -> Maybe Result
do_something_possibly x = do
    y <- do_x x
    z <- do_y y
    blah <- do_z z
    return $ whatever blah z y x

edit: thwarted by HTML. Also, modified example to better illustrate problem.

That's not to say that variables are never useful, but usually they only add clarity when they're used all over the place.

Now, to solve this problem, you don't necessarily have to introduce the concept of unnamed variables. Instead, you can create constructs that raise the code up to the problem domain.

(The solution to the above problem would be to automatically sequence embedded actions. Basically you'd wind up with something similar to what you'd get in a non-referentially transparent language.)

edit: fixed odd spelling errors. wtf was "confessionally" supposed to mean?

Don't discard the current "look and feel," expand on it

Historically(at least, so it seems to me) most approaches to rethinking the source editing interface are very "all-or-nothing" and replace some fine aspects of text with a profusion of boxes and arrows and clicking, conflating many different kinds of user interface elements together.

My thought is - get away from the surface aspects and hype of GUI. GUIs are for browsing. Hotkeys are for heavy-duty interaction - memorize once and you can do everything "in a few strokes." Typing is for everything in between, and has some of the disadvantages of both - a very poor compromise. So I want to someday make a system that is primarily focused on editing with hotkeys. But the overall look of the source and the editor will still be primarily textual.

There are many instances where I want to use more than one dimension to describe code. What we always turn to is names, which can bind many-to-one instances, but excel only at that. Spatial relationships could take over the duties currently performed by names - not all, but at least some of them.

So my current concept, which I'm going to try to work on sometime very soon(days): A system controlled by hotkeys, which lets you view 2 or more dimensions of code, and let you bring up the kinds of relationships that names would normally be used for. The source code could still "look" like a typical text syntax, but instead of starting from text and parsing downwards, it would start at the abstract level and reformat. If better interface ideas come up, they can be added later.

Yes, that's mostly what I'm

Yes, that's mostly what I'm envisioning. Though, I am curious what you mean by the phrase "dimensions of code." Could you explain?

Anyway, I suppose it wouldn't hurt to explain my ideas, although it is slightly off-topic. At the moment I have 3 different constructs which I have in mind to eliminate useless "temp" variables.

1) unnamed parameters

These would be useful if you're defining a small function or lambda where named parameters are overkill. Normally you would use function composition to eliminate these, but that occasionally adds cruft in complex nestings. Example:

Named arguments:

nubBy (\x y -> (gcd x y) /= 1)

Function composition:

nubBy (((/=1).) . gcd)

Unnamed parameters:

nubBy [(gcd $0 $1) /= 1]

Of course, it's not that much shorter, but it does eliminate the useless names. I should point out that, in a graphical editor, you wouldn't need to use sigils or anything—you could get by with a colored red box surrounding the number or something. You would obviously need to specify what parts of the expression go in the lambda, which is why I used brackets above. Again, you could render this however you wanted.

2) graph-based function composition

The basic idea behind this is to remove temporary variables inside a function. This can be accomplished by souping up the usual function composition operator (or, more appropriately, function application). Imagine a normal function application tree, except instead of being rendered with each successive element nested even further, you use arrows to show where results come from and where they go.

Now that you have that interface, there's no reason to keep the current constraints. The results of a function call doesn't have to go to just one place in the expression. Actually, it doesn't even have to be a tree. You could very easily model recursion without having to name the expression and without having to use the y combinator. Just point the results of the expression back to the beginning and voilà. Example:

Temporary variable:

complicated_expression = x a z $ f a
    a = y z z
    z = *some complicated expression*


3) function extraction and sequencing

Basically what the name suggests. The idea is to create a notation that automatically sequences nested function calls. It's easiest to explain with an example:

do_something_maybe x = return doxyz x [gety x] [getz x]

translates into:

do_something_maybe x = do
    temp1 <- gety x
    temp2 <- getz x
    return doxyz x temp1 temp2

I could also see using a system similar to the graph-based function composition idea above. You'd have multiple rows each with 1 expression to sequence in it. You could then direct them to the appropriate location with an arrow (only to later expressions, of course).

The use of trees in PLs and logic

A couple of observations:

1. What we call "text" is actually a graphical notation that evolved over millennia, which represents standardization of certain graphical "icons" (to use GUI terminology). That's worth keeping in mind lest we lose some babies along with the bathwater of fixed-size text (e.g. "plain text", ASCII), which is a much more constrained medium than text in general.

2. Fixed-size text is used as a serialization format for the abstract syntax trees of programs. As such, it's simply a user interface to the syntax tree, which people often tend to confuse with "the program" because users often confuse interfaces with the things they interface to. This raises a couple of related points:

(a) If your graphical language is simply going to be a graphical interface to the same syntax tree, that's a pretty trivial task - why hasn't it taken over the world already?

(b) If you want to explore the freedoms offered by arbitrary graphical structures, going beyond syntax trees, and developing some "new kind of programming", you have to watch out for things like lost proof properties. Trees are useful things for logic and proofs — Smullyan's 1968 book "First Order Logic" starts out with the words "Trees will play an important role in this work", and goes on to define them. (By page 9 it's giving diagrams of abstract syntax trees of logical formulas, recognizing the graphical perspective.) Abandoning the constraints of trees may offer radical new possibilities, but will likely also introduce radical new intractabilities.

(Actually, syntax trees are really graphs in which connections that would break the constraints of a tree are represented as names. But the factoring out of those non-tree-like connections has semantic significance, it's not simply an artifact of the use of trees.)

1. What we call "text" is

1. What we call "text" is actually a graphical notation that evolved over millennia, which represents standardization of certain graphical "icons" (to use GUI terminology). That's worth keeping in mind lest we lose some babies along with the bathwater of fixed-size text (e.g. "plain text", ASCII), which is a much more constrained medium than text in general.

Yes, I agree. Far too many people take "graphical languages" to mean some radically different interface, when it doesn't necessarily have to be that way. Even if you don't add anything new and just use the normal concepts you still gain quite a few advantages. Not to mention the fact that even the concept of shoving something like code into text ("plaintext") sounds like a hack. Of course, it's a well grounded hack with an obvious purpose, but it's still a hack nonetheless.

(a) If your graphical language is simply going to be a graphical interface to the same syntax tree, that's a pretty trivial task - why hasn't it taken over the world already?

Presumably for the same reason functional programming hasn't take over the world yet? I understand why you're asking this, but it's rather difficult to come to a meaningful conclusion after answering it. On the one hand, the idea could be completely bogus, which certainly would explain why it hasn't taken off. But then, maybe it's because nobody ever bothered to explore the idea. This refers back to the point I made previously. I'm not sure I've ever seen a "graphical programming language" that has had even a semi-normal way of displaying code. (If there is one, I'd love to know about it.)

Thanks for your thoughts. I do love thinking about the various things people bring up.

Typing Was Proceeded By Printing

I think the cautionary tale starts too late -- it should start with the people of pens, move to the people of presses and finally touch on a conundrum among the people of keypads. Computing is an outgrowth of previous information technology, and it leverages literacy and the conventions of literacy to a great degree.

What is great about the text interface is not that it reaches for something newer than cards -- keyboards and CRTs -- but that it reaches for something older: letters and numbers in familiar shapes. As UTF8 grows up, i hope to see more of these letters and numbers -- Σ for summation, λ for lambdas, and of course π -- make their way into programming languages.

There are two barriers to "visual programming" -- technical matters, like cross platform representation; and a lack of established lexicon. There may be a coherent "visual" writing system out there -- one where not only the words are pictures (as in Chinese) but also grammatical relationships are expressed pictorially (no language I have ever heard of) -- but I've never seen a graphical programming project reach back to find it. They all start from scratch, inventing not only the technology but also a coherent system of communication.

In short, text is useful not because it is new but because it is old. Where is the "old" in this visual programming stuff?

Careful, assumptions are

Careful, assumptions are dangerous :-) Just because a language has an editor with a GUI, it doesn't mean that all text in the language has to be replaced by visual concepts. Actually, if you wanted to, you could render code in plain text. Even then you'd still have a few benefits over a merged storage/viewing format.

I tried to be as clear as I could on this matter in the essay, but it was difficult to do that and keep the allegory format. I was hoping the seemingly valid comparisons I made would encourage people to think about the matter a bit more thoroughly. I wonder if I would've been better off writing it with a more traditional form.

Maybe program source should be stored as...

abstract syntax trees, in a form not intended directly for human editing (though use of XML or some other human-readable transport would make editing possible in a pinch).

Various well-defined ways of presenting the tree to the user for manipulating and viewing, including a more human-readable/writeable text format, all with well-defined means of converting to/from the internal form, would be used.