Why would one bother to learn a made-up language? Whenever I talk about constructed languages this question seems to come up. The most obvious reason is common to all (non-artistic) constructed languages: they have a smaller vocabulary and a more regular grammar, so they are all faster to learn and easier to use than any natural language. This actually helps you twice: first, because you gain a second language much faster than if you study a language far from your native tongue, and again, because going from language #2 to language #3 is much easier than going from language #1 to language #2. (Someone will substantiate me with that study of people who spent two years studying Spanish versus people who spent one year studying Esperanto and one year studying Spanish, who got further than the all-Spanish control group.)

Now, each of the constructed languages has a particular appeal:

  • Toki Pona has just 120 words. You can literally learn the whole thing in a week to a month.
  • Lojban is radically different from other languages and very precise, despite having a total vocabulary of about 2000 words. You can quickly learn enough to say quite complex things!
  • Interlingua can be comprehended by anyone who speaks a Romance language, even if they do not know Interlingua! It is probably the most actually useful of the languages on the list.
  • Esperanto has the largest community of any constructed language, with its own culture and media. Knowing it gives access to couches to sleep on in many countries across the world.

Learning any language is hard! But these are somewhat less hard.

January 1, 2016 language






The other day I answered a question on Stack Overflow that had to do with traversing a maze. Somewhat more idiomatically, the code would have looked like this:

mazeCell(Maze, What, X@Y) :-
    nth0(X, Maze, Row),
    nth0(Y, Row, What).

Before I explain what’s special about this, let’s reflect for a moment on Prolog. Paul Graham once observed:

You often hear that programming languages are good because they provide abstraction. I think what we really like is not abstraction per se but brevity. A way of expressing programs that was more abstract, but made your programs longer, would not be very enticing. (This is not just a hypothetical example. It happens in Prolog.)

Why might Prolog have a reputation for being expansive rather than brief? One reason that comes to mind is that Prolog doesn’t actually have block structure. Each basic block usually has to become its own predicate.

Before I cower in defeat, let’s think about this maze problem. If I were writing in an object-oriented language and I wanted to create this maze abstraction, I would create an object to represent the maze, called Maze. I would add a method for finding what’s in the maze at a particular coordinate. I’d want a method for iterating through the maze, and maybe another one to look up the coordinate for a particular value. That last one, I may need to write a couple ways, one that returns all the occurrences, one that returns just one occurrence. I’d probably also want a class for the coordinate pairs, so I could treat them atomically, and maybe some class to combine a point and a value for the iteration scheme. In the end, I would wind up with probably seven or so methods and probably two or three classes and interfaces. It would look something like this:

public class Point {
  public int x, y;
}

public class Maze implements Iterable<MazeLocation> {
  public class MazeLocation {
    public Point location;
    public char value;
  }

  public Point                  locationOf(char value) { /* ... */ }
  public List<Point>            locationsOf(char value) { /* ... */ }
  public char                   valueAt(Point point)   { /* ... */ }
  public Iterator<MazeLocation> iterator() { /* ... */ }
  ...
}

What’s interesting about mazeCell/3 is that it actually can do all of those things at the same time. mazeCell(+Maze, -Value, +Point) (i.e. calling with a ground maze and point) returns the value at that point, equivalent to Java #valueAt. Calling with just the maze (mazeCell(+Maze, -Value, -Point)) iterates the maze, like Java’s #iterator. Calling with the value and the maze (mazeCell(+Maze, +Value, -Point)) searches the maze for that value, like Java’s locationsOf and locationOf. No new types were needed to represent a combination of multiple things; Prolog has no problem returning” multiple values. Defining a new operator like @ is trivial.

You may object that the type and internal structure of the maze is not being hidden, and that may be true, but mazeCell/3 doesn’t reveal bits of that structure directly. You could change your representation of mazes and just change mazeCell/3; if all your other interactions with the maze go through it, they will continue to work. There is some loss of encapsulation (though Prolog implementations typically have modules which make it possible to regain it) but the inner structure can be mostly ignored since most queries can just go through this one relation.

What’s really going on here is that we are not defining a method” to iterate mazeCell, we are defining a relation between a maze, the locations in the maze and the contents of those locations. The relation is more abstract than a method; that’s why it encompasses so many different procedures in the procedural domain.

So I dispute Paul Graham’s assertion. The Prolog code for some procedure may be larger than equivalent code in other languages. But you actually buy something for the higher abstraction: much greater flexibility, and that winds up paying off harder. The code for mazeCell/3 may be long compared to locationOf in Java, but you have to write essentially the same code four or five times where in Prolog, you could write it once. The total savings are big.

December 4, 2015 prolog






I’m a big fan of Haskell. Really big. It’s my other favorite language besides Prolog. And there can be no question that a significant aspect of Haskell is its expressive and powerful type system. In a sense, it’s the face that launched a thousand type systems. There was recently a bit of a row about dynamic and static languages (in my opinion this is the winning post) and I won’t rehash it here. Instead, let me trash a few idiotic arguments for static typing that arise in web development.

Statically-Typed SQL Generation!

This one really grinds my gears. First of all, there is not a single (to my knowledge) complete statically-typed wrapper around all of SQL. The static framework du jour probably supports some common subset” of SQL that MySQL, Postgres and SQLite can do. This is a really awful subset to work with, yoking the oxen of Postgres and SQLite to the ass that is MySQL, but this isn’t my point. My point is, how often have you seen an application of yours get into production, only to have the SQL fail because of compile-time detectable type errors?

The answer is zero. This has never happened to anybody. Sure, you’ve had SQL injections. And it’s quite likely that your framework prevents them—nevermind the categories of valid and safe SQL that are excluded from it in the process. But it has literally never happened that SQL that worked when it was committed stopped working in production because of some unforeseen type issue.

Why is that? Because you write SQL interactively and you don’t commit it until it actually works.

There are plenty of interesting frameworks out there for SQL. The most compelling ones I’ve seen lately are Postmodern for Common Lisp and SQL Alchemy for Python. I have a certain appreciation for myBatis. The rest are taking an elegant-albeit-verbose external DSL (SQL) and replacing it with an inelegant, limiting, frequently also verbose internal DSL.

This is a non-problem, folks! Don’t waste my time solving it.

Valid HTML Generation!

Whoopee, you solved the hardest problem of all! My HTML is now going to be valid!

Funny story: it almost does not matter at all if your HTML is valid. Being valid won’t make it render properly. Nobody can tell or care if your HTML is valid.

Similar to the above, what happens with your static generator when WHATWG releases new elements? Do I have to circumvent your system, or do I have to wait for the next release? This was a real pain with JSF and HTML5.

Other Considerations

Note that there are things you can do for me with your library that I may value. For instance, Postmodern is able to give me a level of compositionality that is kind of missing from SQL. That’s nice. But the only way for it to really support all of SQL is by having a generic process for converting s-exps into SQL. You don’t have to get a new Postmodern whenever a new version of Postgres comes out to use new features. That’s the flipside of the type checking argument. If you wrap a lower-level system that has worse type checking than your language, you have to basically code that other system from scratch with your types. What are you buying with all that effort?

The other irksome thing about wrapping both SQL and HTML, but especially SQL, is that you’re trying to treat something high-level as if it were low-level, in something that you believe is high-level, but is actually lower-level. You cannot really have a procedural wrapper around SQL and have it be more powerful than SQL, which is declarative. The best you can hope for is a procedural library for writing SQL statements. And that’s what Postmodern and SQLAlchemy do, and why they don’t get into as much trouble as Hibernate does.

December 3, 2015






By augmenting human intellect” we mean increasing the capability of a man to approach a complex problem situation, to gain comprehension to suit his particular needs, and to derive solutions to problems. Increased capability in this respect is taken to mean a mixture of the following: more-rapid comprehension, better comprehension, the possibility of gaining a useful degree of comprehension in a situation that previously was too complex, speedier solutions, better solutions, and the possibility of finding solutions to problems that before seemed insoluble.

— Douglas Engelbart, Augmenting Human Intellect: A Conceptual Framework (1962)

I think we have a very weak notion of how to improve the life of a scientist. As user interfaces go, a programming language offers nearly the full capability of the machine at fairly high abstraction, with significant up-front comprehension costs. (Similar to compression: you say less, but it’s because both you and the machine have more complexity.) The GUI offers almost the opposite; a well-designed GUI is intended for beginners, to take them up to either an intermediate or advanced level of use, but wholly interactive.

I think this represents a nice divide into two classes” of computer user: the user” who is a permanent underclass, and the developer” or programmer” who is a permanent overlord. Business and government like this; the former because it’s hard to sell something open and modifiable without giving away your secret sauce; the latter because they don’t want clerks suddenly differentiating from each other in terms of productivity or finding and changing anything. This is why Smalltalk failed, in my opinion. It’s hard to convince businesses to deliver apps that are fundamentally open to modification. Intellectual property and all that.

(Incidentally, you now see that business has discovered it’s possible to make the developers the middle class under themselves and the law.)

I don’t think this is a necessary state of affairs. Unix, Smalltalk and Lisp all anticipated the existence of a whole spectrum between low-level developers through users-that-program, through power users, to complete grunts. The whole Unix proposition was that your local wizard would prepare you C programs on-demand and the user-operators would string them together with shell scripting on-the-fly. Smalltalk and Lisp both supplied open worlds” where the user cooperated with the system in a similar fashion using the local metaphors: creating objects or functions or what-have-yous, but able to modify the whole system interactively. The user of a Smalltalk system is basically a programmer. The Liskov substitution principle is really just a way of respecting that relationship as a good actor.

I frankly think it’s a little insulting to system analysts to assume that because they’re not programmers, they cannot fathom some kind of inbetweener system that maybe isn’t as brutal as full programming but also is substantially more powerful than using a GUI. And the real problem with the GUI, IMO, is not what it does to the user experience, it’s what it does to the development time—“the Programmer’s Full Employment Act.” A feature like subarrays is really quite simple in the model. It’s the layer upon layer of goo that has to be created and maintained which makes it so expensive. And it will finally culminate in something like an insolent child; not really knowing what it is doing or why, in severe need of more discipline.

The scientists are similar to the analysts. It seems strange to me to make them crawl through page after page of forms for submitting their scheduling block, only to give them essentially Python plus some libraries in the form of CASA for reducing the data they get. They obviously are able to grasp programming constructs—why do we force them, at great internal expense, to tolerate a UI that coddles them wrongly and then gets in their way?

A friend of mine likes to use the word operator to describe this class: people who are neither wholly victims of the GUI/programmer’s whims nor fully liberated programmers themselves. They use software that may be have required some training to understand. The software works more like their servant or peer than their boss.

I think that is what Engelbart foresaw in software as a tool to augment intellect. We got very distracted by the idea of direct manipulation, although now I think we build GUIs out of more of a cargo-cult sensibility than principle. But even that was a distraction from simpler, earlier principles: help humans comprehend faster and better and speed them to better solutions to problems. Maybe if we accept a little ugly, we can get there faster and more intelligently with less work.

November 24, 2015






Which language is more expressive, Lisp or Haskell?

I want to encourage you to forget the word expressive,” or at least, strive to give it a particular sense in your language advocacy, because it means different things in different contexts, often nuanced and slightly contradictory things.

When Lisp is promoted as an expressive language, what is meant is that there is a complete macro system, and it is not difficult to write either abstract code or quite frankly machine-friendly, near-optimal code. But when Haskell is promoted as an expressive language, what is usually meant is that it has an extremely powerful type system that can express very abstract ideas. Few people seem to know it has a complete macro system inspired by Lisp—this does not seem to be a factor in its expressiveness.”

In a certain sense, every strongly-typed language is less expressive than a weakly-typed language. Many classes of error that the strongly-typed language prevents the weakly-typed language would allow. There are literally more expressions” in the weakly-typed language. This loss of expressiveness” does not seem to keep advocates of Haskell from getting enough sleep, even though there are certainly programs that do not type check (or could not be made to within the confines of any particular regime) that are nonetheless correct, despite their unlikelihood.

Any program that my machine can execute can be written in assembly. Does that make assembly the most-expressive language? What if I want to say one thing and have it mean the same thing on different machines? Portability, in other words. If that constrains my options, does that also reduce expressiveness or improve it? Can you say more with haiku or with any random jumble of words?

A J program might be abstract over matrix dimensions for free. Can something be more expressive sometimes and less in others, depending on the context?

How does high-level” vs. “low-level” fit into this? Prolog is more high-level;” it has actual relations rather than just functions, and it will often figure out what you mean without you telling it how to do it. Yet, as Paul Graham once observed, it often actually requires more code to make a program in Prolog. And if it is more high-level,” why did the Fifth Generation Project fail, and why does it sort of languish as an interesting class project but not widely used today?

More questions than answers, as usual.

November 12, 2015






People often ask me which functional language they should study first. This is my road map” to functional programming languages.

Clojure is a very nice, highly pure functional language. It’s an untyped Lisp language, which means it emphasizes syntax macros, but it is just a really nicely designed language, very well-suited to data processing and gluing together Java libraries.

Haskell is the flagship typed functional language. Lots of ideas in FP reach their high water mark in this language, which is famous for being difficult to learn and very mind expanding. If you’re interested in terseness and correctness, it’s recommended, but it can require some study before being able to use it in anger.

Factor is, IMO, the to-beat concatenative language. It’s a very different computational model, similar to Forth, where everything is a stack operator, but object-oriented, principled, and has a large and helpful standard library, making it easy to do things like build trivial GUIs and do XML processing.

Prolog is the go-to declarative/logic programming language. Great for learning about non-determinism and doing natural language processing, it has a built-in database and generic parsing framework. The flagship implementation is SWI-Prolog, which has a rich standard library, though the language has a lot of crufty spots due to its age.

J is the open-source array-oriented functional language. In the tradition of APL (which defined its own character set), it is based on the idea of matrix operators and implicit iteration. Its relatives are widely used in finance. The language is basically unreadable to the untrained eye but reaches new levels of terseness.

These represent, IMO, nice local maxima.” Underneath most of these there are some nice variants that present somewhat different tradeoffs with the same basic flavor.

Under Clojure, you’d find other Lisp variants, namely Racket, Common Lisp (SBCL, Clozure), Scheme (Guile, Chicken), newLisp, and LUSH, which each represent different tradeoffs: Racket is a nice learning environment based on Scheme but with a vast built-in library; Common Lisp is closer to C++ in terms of size, features and pragmatism; Scheme is a tiny academic language with many incompatible implementations, newLisp and LUSH are specific Lisp implementations with small domains (one of which is scientific computing).

Under Haskell, you would mostly find OCaml and Standard ML (SML/NJ, Moscow ML, MLton, Poly/ML), which are smaller and simpler languages. OCaml has a vibrant pragmatic community centered around finance where Standard ML is used almost exclusively in academia. The CLR implementation is called F#, and mostly resembles OCaml; Scala would be the JVM language most similar to Haskell. I personally have a small beef with Scala because I think it is the worst of both worlds,” both large and complex, hard to comprehend, and by supporting all of Haskell and Java, it winds up being a bit too big and kitchen-sinky. But it has its fans, particularly at RiskSense. Standard ML is more like Scheme: an academic language with a tiny core. It’s famous for its package system though, which only OCaml really does justice to—even Haskell doesn’t have as much power, here, though type classes are pretty convenient. Mythryl is another ML-derived language, a bit closer to C.

Under Factor there is basically Forth, which is still supposedly used by embedded systems (every Forth is different) and Joy, which nobody really knows, an academic exercise that never really went anywhere.

Prolog really only has Logtalk, which is a powerful object-oriented extension, and a few really obscure attempts to modernize it, whose names escape me. Prolog is not widely used, but much more so than any other language in this category (except maybe SQL, if you count that.)

Finally, J has Kx, which is not free, and APL, which is also not free and quite odd (Dyalog being the flagship APL implementation.) But the arguments for the other ones are not especially strong.

October 14, 2015