Showing posts with label programming-languages. Show all posts
Showing posts with label programming-languages. Show all posts

Wednesday, August 02, 2017

How important is decidability in programming tools?

Hoisted from the drafts folder because the discovery that TypeScript's system is Turing-complete is making the rounds.

It's a common assumption in the programming language community that practical type systems should be decidable. Or, at least, it used to be: in the early 2000s, I had a grad school colleague who spent a lot of time trying to invent restrictions that made the type system of Cecil decidable, and people seemed to feel that his formalization of Cecil would be unreasonable if he could not solve this problem.

Over a decade later, it's well-known that Java with generics and wildcards was undecidable for years before people even realized it. Furthermore, devising restrictions to the type system that achieve decidability seems to be an open research problem.

Did hundreds of thousands of Java programmers experience an existential crisis when Java with generics was found to be undecidable? Are they waiting with bated breath for researchers to solve this urgent problem? I'm pretty sure 99.99% of them don't know that the problem exists and won't notice if it's ever fixed.

Meanwhile, the PL research community has mostly gotten bored of object-oriented languages and type systems thereof, and moved on to other things. And the functional programming community (or some fraction thereof) has embraced Scala, whose type system is also undecidable.

Conversely, it is well-known that in ML, it is possible to write a program by hand on a single sheet of paper that will take longer than the lifetime of the universe to typecheck, because Hindley-Milner is superexponential in the worst case.

What is the practical difference between a typechecker that can hang until the universe is a cold, featureless void of uniformly distributed entropy and a typechecker that can hang forever? In both cases, you would hit Ctrl-C after a decent interval and rewrite your program. Would it make much difference if ML's type system were undecidable? Probably not.

I remember standing up at an ECOOP talk one year and asking a question along those lines. The researchers had made a big deal about the importance of decidability for the problem they were solving, and I asked why it was so important. The presenters seemed to think the question was ridiculous and I'm pretty sure everyone else in the room thought so too. I probably didn't word my question well — I wasn't a good researcher and I'm not proud of my time in academia — but I still think I was basically right that one time.

The important thing is that tools have tractable runtimes for the programs that people want to write. Unfortunately, "tractable runtime for reasonable programs" is much harder to demonstrate using the formal and empirical tools that exist today than "decidable for all syntactically valid programs". And the gap in available intellectual tools has led a research community to handcuff itself needlessly in hunting for useful results.

Tuesday, September 16, 2014

The world's most popular functional language, and what it teaches us

I realized today, when I read the phrasing of this LtU post, that my last two posts were too pessimistic about functional programming languages. There is, of course, at least one very popular functional programming language, and that is Emacs Lisp. Emacs Lisp is even widely used, at least a little bit, by countless programmers who never use any other functional programming languages at all. But this just confirms my original hypothesis that language popularity is driven almost entirely by platform, not by characteristics of the language itself.

Monday, September 08, 2014

More on programming language adoption, from Meyerovich and Rabkin

A little bit of vindication from Meyerovich and Rabkin; a quote I found particularly interesting (emphasis added):

A given prior language only occasionally correlated with the choice of a specific different language for the next project. Most notably, developers have high propensities to switch between Windows scripting and application languages, such as VBScript and C#. These languages also correlate with Microsoft web-development languages such as ASP. Such correlations are also visible in the results of Karus and Gall [12], who found groupings such as WSDL and XML being used in conjunction with Java.

Notably, we do not see significant exploration within linguistic families. There is a relatively low probability of switching between Scheme and LISP, or between Ruby, Python, and Perl. We conclude that developer movement between languages is driven more by external factors such as the developer’s background or technical ecosystem than by similarity of the underlying languages. This implies that language advocates should focus on a domain and try to convince programmers in that domain, instead of trying to convince programmers who use languages with semantic similarities to the new language.

Note that this clearly weighs against the Chaudhuri/Hicks hypothesis that education or unfamiliarity with functional programming is the "real problem". If developers tended to choose languages based primarily on comfort and familiarity, then we would expect them to switch more frequently among languages within a family than across families. Instead we observe the converse pattern: developers switch quite freely between programming language families whenever they need to do so in order to get work done in their domain.

In fact I think Meyerovich and Rabkin are too tentative in their formulation (maybe appropriate in an academic paper, but here we don't need to be so tentative). I think it is quite unlikely that developer background is a major deterrent to new language adoption. To repeat something I said the other day, developers routinely learn all kinds of weird, complicated, and frequently frustrating technologies in the course of their work. New programming languages are not fundamentally harder than all these other technologies, and programmers will learn them when they need to in order to get work done. The problem most unpopular programming languages face is simply that nobody needs them to get work done.

Overall, people who wish to change the mix of programming languages currently in use should spend less time extolling the virtues of their language (and criticizing competing languages!), and much, much more time developing platforms and libraries to make their language of choice a stellar tool in some concrete domain.

Tuesday, September 02, 2014

Is education to blame for functional programming's minority status?

Rice University's Swarat Chaudhuri asks (and attempts to answer) the perennial question: why isn't functional programming more popular? I have my own long-running theory about why programming languages become popular (or don't), but first let me dispute a couple of specific things in the linked post. Chaudhuri writes:

The same survey also showed that the factor that correlates the most with preferring and using a language is the availability of libraries. This is certainly behind the meteoric rise of, say, Python. However, it seems implausible that this factor is the primary reason why functional programming is unpopular. If it were so, the F# language, which allows functional programmers to utilize the entire .NET infrastructure, would be a mainstream language by now. There’s no indication it will be any time soon.

I think Chaudhuri dismisses the hypothesis far too lightly. Here are three obvious reasons why F# is not a counterexample:

  • I have never programmed in F# (although I've done a little OCaml, and I gather they're almost identical), but my long experience with cross-language interoperability makes me suspect strongly that accessing nontrivial C# libraries from F# is nothing like using libraries written idiomatically in F#. It probably feels much more like calling through a foreign function interface — for example, like accessing Java classes from Jython, except possibly worse, because C# is not only a different language but a different programming paradigm.
  • There are a large variety of inevitable network effects that come from using a single language within a project. If you are going to use mostly C# libraries in the .NET ecosystem, then a sensible project manager is probably going to choose to implement the project itself in C# rather than F#. This is especially true if libraries would force you to write a lot of your code in a semi-OO style within F# anyway.
  • The .NET ecosystem has never had great mindshare in the communities where most of the "hot" industrial software development is happening: open source, backend software running in the datacenter, web development, and mobile development. Spend a little time walking around Silicon Valley and San Francisco, and see how many hackers are using Windows. If, somewhere in the sea of Macbooks, you even glimpse someone using a Thinkpad, there's an excellent chance that it's running Ubuntu. Conversely, if you see someone using Windows, there's an excellent chance they're a business suit from a large corporation (at startups, even the businesspeople use Macbooks).

    In fact, this was almost as true, last I checked (years ago, admittedly), even within the programming language research community. It is startling to me that a programming language researcher would look around, observe almost nobody they know hacking on Windows, and still ask why F# on .NET has not taken off.

    (Mono notwithstanding, my understanding is that Microsoft has never made it a priority to make .NET development a really great experience on non-Windows platforms. C# may have a lot of libraries, but Mono has always been a second-class citizen and there is an excellent chance that large swaths of the C# ecosystem depend on APIs (or, worse, subtle implementation quirks) specific to Microsoft .NET. I suspect any prudent project manager looking at the .NET ecosystem is unlikely to bet the farm on Mono.)

Next, Chaudhuri goes on to argue that the lack of university education in functional programming is to blame. Well, I won't deny that this is a contributing factor, but: few CS schools these days teach Ruby or Perl or Objective-C, yet those languages seem reasonably popular; few CS programs teach more than rudimentary use of version control, but git (i.e. the most complex version control system known to humankind) seems popular; few CS programs teach web frontend development frameworks or MVC or template metaprogramming or MapReduce (at least, not until recently, and certainly not in intro level classes), yet all those things and many more have managed to achieve significant adoption in industry.

In short, professional developers routinely adopt all sorts of complex technologies that are not taught academically. As cool as functional programming is, I just don't believe it's fundamentally that much weirder or harder than all the things modern developers use every day. If I had told you a decade ago that in 2014, a nontrivial number of professional programmers would be writing server applications and developer tools in hand-rolled continuation-passing style, you would have looked at me funny; yet here we are!

So, then, how do I explain the relative unpopularity of functional programming languages?

First, I would observe that most programming languages are not popular, period. People have invented tens of thousands of programming languages, and nearly all of them languish in obscurity. Only a very select few manage to achieve popularity. Given that functional programming languages are a minority of all languages, we should naively expect a minority of popular languages to be functional, just from random selection. The null hypothesis does a lot of work here.

Second, I would observe that nearly all popular programming languages seem to be hybrids. Consider a different programming paradigm: Smalltalk-76 was purely "object-oriented" (everything is an object, every object has a class, every class has a superclass, objects communicate strictly by sending messages), but its most popular descendants seem to be hybrids. For example, C++, Java, and Python are not purely OO.

Therefore, we should expect that a popular functional programming language would also be a hybrid. And indeed when you view things in this light, many popular languages today have adopted bits and pieces that were once viewed as features of functional programming, such as automatic memory management, first-class lexical closures, and parametric polymorphism. Functional programming purists no doubt view this ad hoc borrowing as hopelessly inadequate cargo-cultism that misses the fundamental point of functional programming, but it is nevertheless exactly what we should expect from the gradual popularization of functional programming. In the essay Real Programming in Functional Languages (1982), J. H. Morris Jr. memorably wrote:

Functional languages as a minority doctrine in the field of programming languages bear a certain resemblance to socialism in its relation to conventional, capitalist economic doctrine. Their proponents are often brilliant intellectuals perceived to be radical and rather unrealistic by the mainstream, but little-by-little changes are made in conventional languages and economies to incorporate features of the radical proposals. Of course this never satisfies the radicals, but it represents progress of a sort.

I therefore claim that some small part of FP's "unpopularity" is apparent rather than real.

However, I admit that even the combination of the previous two explanations does not seem sufficient to explain why no primarily functional programming language has become the default way to program in a popular domain. But I don't think education is enough explanation either.

So I have to fall back on my primary theory: I maintain once again that languages reach popularity via platforms.

Thus, for example, Swift will probably be a big deal, independent of almost any qualities it has as a language. Apple is the dictator for the iOs platform. It seems likely that Apple will eventually make Swift the default way to program on iOs. Therefore, Swift will become popular, despite the fact that zero people graduating from university computer science programs in 2014 were taught Swift in school.

If functional programmers want FP to be a bigger deal, then my personal recommendation is:

  • develop an industrial-quality platform for doing something that large numbers of developers really want to do, and
  • evangelize the hell out of it, with a seriousness matching that of professional DevRel teams: videos, tutorials, books, portfolio-quality demo sites in GitHub, reliable turnkey commercial hosting infrastructure if need be, etc.

Web development is one good candidate domain, since (a) web development is a clusterfuck and thus ripe for improvement; (b) web developers are culturally eager to try the new hotness (in fact, arguably a little too eager); (c) you can reach a large audience without requiring any hard technology transitions of users since everyone has a web browser.

Look, for example, at how Rails lifted Ruby from relative obscurity to the default way (at least for a little while) that startups built websites in the Valley. The web framework space is more crowded today, but the field for new ones still seems fairly open, as long as you bring something new to the table. For example, focusing on realtime interaction seems to have bought Meteor a lot of buzz, despite the fact that its backend is currently built on a broken database.

Personally I think there is an opening for a "better PHP" — for all PHP's WTF/lol, if you study Keith Adams's talk "Taking PHP Seriously" (slides) it is clear that the PHP runtime does a few things right that no other platform currently does. Of course, at this point, you're probably laughing at the notion that a bunch of functional programming mandarins is going to successfully devise something for the median PHP programmer to pick up and use. But that is the type of work that might make functional programming the default way to do stuff.


EDIT: For more evidence that Chaudhuri and Hicks are wrong, see Meyerovich and Rabkin's study on language adoption.


p.s. Bizarrely, in a comment on Chaudhuri's post, Bob Harper (whom I have tremendous respect for) claims that Java doesn't have a conditional expression. What? Am I missing something?

  Object x =
    boolExpr1 ? valExpr1 :
    boolExpr2 ? valExpr2 :
    boolExpr3 ? valExpr3 :
    defaultexpr;

Is this not just cond with somewhat uglier syntax?

Tuesday, February 18, 2014

Why should Mozilla continue developing Rust?

The title of this post is not (entirely) rhetorical. I'm puzzled by Mozilla's decision to burn several of its full-time engineers' cycles on the Rust programming language. Maybe someone can enlighten me. I offer the following observations with all due humility.

As a problem of engineering management, programming language development can be analyzed in terms of cost, risk, and return. I do not see how Rust makes sense for Mozilla along any of these dimensions.

Cost: Getting a new programming language off the ground only requires a handful of people, if you have the right people. For giant technology corporations, which have thousands of engineers on staff, that's a tiny relative overhead, well within the margin of a sensible research budget. By contrast, for Mozilla, a lean, low-headcount organization, it's a major opportunity cost. A handful of Mozilla's top full-time developers represents a big bite out of Mozilla's engineering throughput.

Risk: The baseline probability that a new programming language will become popular is low. It is even lower when you cannot use the popularity of a platform to strong-arm external developers into adopting it (the existence of such a platform is the story behind the success of JavaScript, Objective-C, and C#). Mozilla has no platform that it can use to strong-arm anyone into using Rust, nor does it even wish that it did. And when a programming language does not become popular, its few sponsors end up doing all the heavy lifting for it indefinitely. The language also remains a laggard behind comparable languages in libraries and tools. Mozilla isn't well positioned to mitigate this risk or to deal with its downside.

Return: The returns to adopting a better language are roughly proportional to the developer-hours spent writing code with it. As a organization with both low headcount and few projects, Mozilla will have difficulty recouping its investment:

  • Consider Google and Go. Suppose 5 core Go developers work on the language for 2 years; this costs about 5 * 2000 * 2 = 20k developer-hours. This investment can be recouped by saving 1000 Google engineers an average of 2 hours per week for just 10 weeks, or equivalently by providing a quality increase equivalent to 2 more hours per week of design, testing, etc. Viewed this way, Go has a plausibly huge upside for Google. But Mozilla will never have 1000 full-time engineers using Rust; it has a few hundred employees roughly 1k employees total, not all of whom are engineers, and few of whom might be writing Rust full-time in the foreseeable future. Perform a similar calculation using any remotely plausible numbers, and the case for the Rust's return to Mozilla comes out pretty weak. Either Rust will take far too long to pay off, or it must be orders of magnitude better than the next-best alternative (and the latter seems unlikely).
  • It is easier to realize the benefits of a better language when starting a new, greenfield project than when rewriting legacy code. In fact, when rewriting legacy code, developers incur more costs than benefits until a tipping point is reached. Google, Microsoft, or Amazon, to take a few examples, each start dozens of substantial projects and hundreds of little projects per year. At such companies, it is conceivable that, by winning over new projects at their inception, a new language could achieve an annual adoption rate of hundreds of developers per year. By contrast, Mozilla can't start more than few projects per year without losing focus. So the rate at which Mozilla can realize the benefit of a new language is constrained even further than their headcount would suggest. And indeed the core developers of Firefox, Mozilla's biggest project by far, will not benefit from Rust anytime soon.

Now, in spite of all the above, one might disregard risk, cost, and return if one had a truly unique opportunity. If you're the only organization in the world that might plausibly deliver on some project of unique importance, then it might be worth rolling the dice: "We have to save the world from X; nobody else will." Perhaps reasonable people can disagree, but I can't see how Rust qualifies. As a "fast, safe, concurrent, static, systems language", Rust is quite comparable to Go or D; even if one grants, for argument's sake, that it's better than those languages in some ways, it occupies a similar space. So Mozilla's opportunity is simply that it has the money and freedom to pay a few software engineers to work on Rust full-time. The "unique opportunity" rationale for overriding cost/risk/reward does not seem to apply.

Alternatively, one might rebut all of the above calculations by saying that Rust is a research project, not strictly an engineering project. But it is a curious research project. Research justifies its existence by hoping to advance computer science in a fundamental way. Rust conversely aims to minimize novelty, as its FAQ states: "Old, established techniques are better [than novelty]". I cannot think of a fundamental computer science question that is investigated by Rust's development. It is research only in the sense that it is a speculative engineering project without an obvious short-term payoff.

Furthermore, all of the above must be considered in light of Mozilla's current position. Mozilla is fighting to maintain relevance in a world where all the major desktop and mobile operating system vendors are shipping high-quality web browsers. And Mozilla is fighting with far less resources than its competitors. Mozilla punches far above its weight, and for that it should be proud, but I doubt that it has the luxury of diffusing its focus at this time. Mozilla is not like the IBM or Microsoft of old; it cannot plow huge surplus profit margins into basic research without subtracting needed resources from product engineering.

Therefore, in my opinion, Mozilla should spin out the Rust project to community maintenance, and try hard to convince its paid engineers to work on something with a cost/risk/return/opportunity profile better suited to Mozilla's place in the world. Rust developers are experts in programming language implementation, so ES6, asmjs, or Firefox and Firefox OS developer tools all seem like promising alternatives.

Or, if Mozilla really believes that reducing dependence on C++ is a major strategic priority, these developers might investigate rewriting Firefox components in another language — one for which they won't have to do most of the heavy lifting in toolchain and library development. Delegating language development to someone else makes far more sense than doing it in-house. By way of analogy, Mozilla does not try to innovate in datacenter design. To do so would be ludicrous, as Google, Amazon, Facebook, etc. are all far better-positioned to do so. Instead, Mozilla is happy to reap the fruits of robust multi-party competition in datacenters. They should take a similar approach to programming language design and implementation (outside of the web client platform, where they are unavoidably a key contributor).

A third alternative might be to find a deep-pocketed external sponsor to take on the heavy lifting for Rust. Samsung made some noise a while ago about sponsoring Rust; but how many active Rust contributors come out of Samsung's headcount rather than Mozilla's? I believe that the key cost of Rust development for Mozilla is the opportunity cost of expert Mozilla developers' labor. Until Samsung or some comparable organization credibly commits not only financial sponsorship but long-term ownership and headcount to Rust development, its costs will not be truly offloaded from Mozilla.

p.s. I say all of the above as someone who likes what I've seen of Rust, purely as a programming language. I would be happy if some organization took up the Rust banner and carried it forward. But I do not think Mozilla is a logical primary sponsor for it.

Wednesday, June 09, 2010

On the verbosity of Java generics and related type systems

So, recently T. B. Lee tweeted:

Java's generics syntax feels really clumsy. Are there other (strongly typed) languages that do it better?

I replied as best I could in 140 characters while riding a crowded Muni bus home after work, but I mangled the explanation, so I think I should rectify this.

First, it is worth comparing Java generics to other languages that have parametric polymorphism. For example, consider ML (and more generally the Hindley-Milner family of languages). In ML, you don't need to write down types most of the time, because of type inference. Whereas in Java you might write:

<K, V> LinkedList<K> keysAsList(HashMap<K, V> aMap) {
  LinkedList<K> result = new LinkedList<K>();
  for (K key : aMap.keySet()) {
    result.add(key);
  }
  return result;
}

in OCaml you can write:

let keysAsList aMap =
  Hashtbl.fold (fun key _ rest -> (k::rest)) aMap [];;

Notice that although we had to annotate all the Java variables with types, there's not a single type annotation in the OCaml code (Hashtbl.fold is the name of a function qualified by its module name; it is not a type annotation). But OCaml is statically typed nevertheless.

So, one might ask, what gives? Why can't you just add type inference to Java?

Well, the short answer is that typechecking Java generics is a fundamentally harder problem. ML has only parametric polymorphism; Java has both parametric polymorphism and subtype polymorphism (i.e. the object-oriented kind). It is perhaps not obvious why this makes things hard until you learn that B. C. Pierce proved in 1992 that bounded quantification in F≤ (pronounced "F-sub") — a formalization of the most straightforward and general combination of subtyping and parametric polymorphism — is undecidable.

In other words, in F≤ it is possible to write programs for which the type checker would not terminate. This is generally held to be a bad thing (n.b. I disagree with the prevailing opinion, but that's a discussion for another day), so over the next decade or so there followed several papers by Pierce and others attempting to isolate calculi weaker than F≤ with type systems that were both usable and decidable. The most practically relevant outcome of this work was Featherweight Java, which provided the formal foundation for (most of) Java generics. C#, Scala, etc. build on this line of work, although in Scala's case fairly indirectly.

What does all this have to do with type inference? Well, nothing directly. But for any given level of type system expressiveness, full type inference is at least as hard as type checking. And the type checking problem for Java with generics already lives close to the undecidability ceiling (in fact, the decidability of Java generics with wildcards is, AFAIK, still an open problem; proving this sort of stuff used to be a hot research subject but I think everyone's gotten bored of object calculi and moved on). Oh, and I should mention that many of the best minds in academic language design have thrown themselves at the parametric polymorphism + subtyping + inference problem at one time or another, and come up empty. Now, none of this is hard proof that much richer type inference for object-oriented languages with generics is impossible, but it all hints strongly in this direction; at a minimum any such system is likely to be exceptionally intricate and difficult to prove sound.

So, basically, I believe that it is unlikely that anyone will come up with a fundamentally more concise type system for a programming style that combines (1) objects, (2) generics, and (3) static typing. At best, people will fiddle around on the margins — using different punctuation, for example, to denote type parameters, or making other parts of the language more terse to compensate.

That said, although general type inference seems hopeless, there are clearly some things that could make Java's generics more syntactically lightweight in certain common cases. For example, it would be trivial to infer the type of a variable at any declaration site with an initialization expression. C# and Scala appear to do some of this.

Tuesday, May 11, 2010

How to design a popular programming language

This has been kicking around in my brain for at least half a decade, and if you know me well then I've probably spoken it aloud in your presence; so it's high time to get it down in writing. Here is my Grand Unified Theory of Programming Language Adoption. There are three steps:

  1. Find a new platform that will be a huge success in a few years.
  2. Make your language the default way to program on that platform.
  3. Wait.

That is all. Note that none of the above steps has anything to do with the language design itself. In fact, nearly all popular languages are terribly designed. Languages become popular by being the "native" way to program a certain kind of system. All of history's most widely used programming languages fit this model — Fortran (scientific programming), C (Unix), C++ (MS Windows), JavaScript (web pages), Objective-C (Mac OS X), . . .

Or, in fewer words: Languages ride platforms to popularity.

Why is this so? Well, to a first approximation, no piece of software ever gets rewritten in another language; and once a critical mass of software for a platform has been written in one language, nearly all the rest will follow, for two reasons:

  • Nobody has figured out how to make cross-language interoperability work well.
  • The network effects from language adoption are immense. Programming is, despite appearances, a deeply social profession. To write successful software quickly, you must exploit the skills of other programmers — either directly, by hiring them, or indirectly, by using library software they've written. And once a language becomes the most popular in a niche, the supply of both programmers and libraries for that language rapidly accumulates to the point where it becomes economically irrational to use any other language.

In fact, I claim that in all the history of programming languages, no language has ever successfully unseated the dominant language for programming on any platform. Instead, a new platform gets invented and a new language becomes the "founding language" for that platform.

Well, OK, there are exactly two exceptions: Java and Python. It took me a while to figure out what happened in those cases, and the answers I came up with were surprising (to me).

Java is anomalous because although it is widely used in its primary domain (Internet application servers), it is not predominant, the way that e.g. C++ is predominant in writing native Windows GUIs. My explanation is that the web architecture has a uniquely high-quality interoperability protocol in the form of HTTP and HTML(/XML/JSON/...). Hey, stop laughing. HTTP and HTML fail all kinds of subjective measures of elegance, but they succeed in isolating clients and servers so well that it is economically viable to write the server in any language. In other words, as unbelievable as it sounds, HTTP and HTML are the only example in history of cross-language interoperability working really well.

I'll abandon this explanation if I can find, in all the annals of computing, another protocol that connected diverse software components as successfully as HTTP and HTML. The only things I can think of that come close are (a) ASCII text over Unix pipes or (b) ODBC, and neither of these provide nearly the same richness or connect components of similar diversity.

Python is anomalous because rather than riding a new platform to success, it simply seems to be displacing Perl, PHP, etc. in the existing domains of shell scripting, text processing, and light web application servers. My explanation is that Python appears to be the only language in history whose design was so dramatically better than its competitors' that programmers willingly switched, en masse, primarily because of the language design itself. This says something, I think, both about Python and about its competitors.

Incidentally, this theory predicts that all the new(ish) programming languages attracting buzz these days — whether Ruby, or Scala, or Clojure, or Go, or whatever — will fail to attract large numbers of programmers.* (Unless, of course, those languages attach themselves to a popular new platform.)


UPDATE 2010-05-15: Reddit and HN weigh in.


*Which is fine. Very few languages become hugely popular, and in fact nearly all languages die without ever seeing more than a handful of users. Being either influential (so that later languages pick up your ideas), or even merely useful to a significant user population, are fine accomplishments.

Sunday, April 11, 2010

Computer science and the iPhone developer agreement

Full disclosure: I work for Google. However, this blog reflects my personal opinions only.

Programming and computer science are not synonymous, but obviously the two are deeply intertwined. The fundamental activity of programming is the construction of abstractions. Programming language design and implementation is one of the fundamental forms of abstraction building. It is central to the field, and has been so nearly since its inception. One of the oldest and most important research conferences in computer science is named Programming Language Design and Implementation.

This suggests a particular understanding of what Section 3.3.1 means. Section 3.3.1 says: "Thou shalt not build abstractions other than those we prescribe." It bans one of the fundamental activities of programming.

This would be a mere curiosity, except for Apple's unusually influential position in the computing industry. All trends point towards mobile devices* becoming much more pervasive than all other general-purpose computing devices. Indeed, the combination of mobile and cloud computing may someday replace all other user-visible hardware except what's needed to support input and output (screens, cameras, etc.). And Apple has the credible goal of becoming the preeminent mobile device provider, setting standards for the industry and defining the entire computing experience for a huge swath of future computer users.

Section 3.3.1 therefore constitutes a direct attack on computer science, delivered by a powerful and well-funded organization that aims to transform laypeople's interface to the field. As long as 3.3.1 stands, for a computer scientist to purchase an iPhone or iPad is akin to a biologist purchasing a textbook that advocates against teaching evolution. Full stop. Go ahead and do it if you can't resist the shiny, but understand the moral weight of the decision you're making.

I can already hear people ready to trot out the standard roster of excuses. Hit the comment box if you want, but realize that I've anticipated the common objections and the only thing stopping me from preemptively rebutting them all is the fact that I'm moving soon and I have a huge number of boxes to pack. To pick just three examples:

Q: "The iPad isn't for people like you. Why do you care?"
A: "This post isn't for people who don't care. Why are you reading it?"

Q: "Apple has a right to do whatever it wants with its platform. If you don't like it, you shouldn't use it."
A: "Thank you for agreeing with me."

Q: "You can program whatever you want in HTML5 and access it through Safari."
A: "Yes, the web is an open platform, which Apple fortunately does not control.** I'm talking about Apple's rules for programming on the platform that it does control."


*A.k.a. "phones". Incidentally, I think the British slang "mobile" is more elegant and generalizes far better any of the {cell,smart,super,...}phone terms that are used on this side of the pond.

**Although I will remark that it's naive to imagine that a platform can be preeminent for very long without influencing the market of content and applications to which non-participants in the platform regime have access. There's a reason Hulu used to work on Flash only. But that's a post for another day.

Tuesday, May 12, 2009

Dynamic dispatch is just higher-order programming

Wow, this is pretty terrible coming from a Haskell programmer (via HN):

Dynamic dispatch is a scary programming technique. When you call a virtual method, you never know what might happen. This makes is [sic.] difficult to reason about such code, and code that is hard to reason about is hard to maintain.

This is true in the exact same sense that when you implement a higher-order function, "you never know what might happen". Here is a naive implementation of map in Standard ML:

fun map f [] = []
  | map f (x::xs) = (f x) :: (map f xs)

f could be bound to anything! OMG WTF BBQ!

Likewise here is a Java implementation of printList:

void printList(List aList) {
    for (Object o : aList)
        System.out.println(o.toString());
}

o.toString() could dispatch to anything! OMG WTF BBQ!

Well hold up man, let's try that in ML:

fun printList _ [] = ()
  | printList toString (x :: xs) =
    (print ((toString x) ^ "\n");
     printList toString xs);

Oh that's so much better isn't it. Or not. Basically, you will note that we had to type toString three times instead of once to achieve roughly the same effect.* Note also that this function only works over homogeneous lists; if you want a heterogeneous list, you'll have to define a union type and pack/unpack it yourself.

Object-oriented programming is a form of higher-order programming wherein related data and operations are tightly bound to each other, thus freeing you from the pain of having to wrap them up yourself, thus making it exceptionally convenient to pass data and functions together. Or, in other words, OO programming is just a functional programming idiom with lots of very convenient syntactic and semantic sugar on top**.

Now, the OO community has plenty of bad code and bad guruism bouncing around. Maybe there's somewhat less of that in the functional world. But IMO that's largely explainable by the fact that there are vastly more working OO programmers and vastly more OO code modules than functional equivalents. If the Haskell or ML community were as big as the Java community, there would be just as much terrible higher-order function spaghetti as there is terrible inheritance spaghetti today.***


* Q: Wouldn't the version using Haskell and type classes be as compact as the OO version? A: Maybe, but you'll still have to restrict the function's domain to homogeneous sequences of StringConvertable instance values. Once I hand you a heterogeneous list, you're back in the land of passing toString and packing unions. The only way to do this right is to introduce existential pack/unpack into your language, which basically amounts to introducing a slightly crippled object system with additional syntactic overhead.

** In particular, making super sends and self sends work correctly without OO sugar gets messy. OTOH, conversely, the object-oriented programming languages in common use make certain other kinds of functional programming idioms somewhat baroque — for example, Java's lack of a compact syntax for anonymous functions is a huge pile of Lose — but that's a discussion for another day.

*** In fact, I strongly suspect that with a fair number of kids today thinking that Haskell is the new hotness, that community's in for a rude awakening as they realize that Haskell's going to require style guides and "Haskell annoyances" books and assorted baroque frameworks in order to allow programmers of average ability to assemble software of similar complexity to that commonly assembled in Java today.

Saturday, May 09, 2009

Robert Martin + Ruby = ughhhh

A recent talk by Robert Martin on Smalltalk and Ruby is generating a lot of buzz today. Now, I just gave you the link to the talk, but don't take this to mean that I think you should watch it. I had a whole long writeup-in-progress about all the different kinds of Wrong embodied by this talk and its reception. But there was so much to explain, so many kinds of Wrong, that I just gave up.

Instead, I'll give you an abbreviated summary of a few reactions:

  • Holy shit, Martin is long-winded. A talk of this length with so few ideas* is offensively disrespectful of its audience's time.
  • Estrogen = weak and insipid? Really? Without a hint of irony? And not a raised eyebrow in the room? WTF?
  • The fact that many Ruby hackers seem to think that this was a good talk shows how bad that community's taste is.
  • Twitter's 140 characters are completely inadequate for discussing a subject like this; on the other hand it's a great medium for saying AOL! Which is, I suppose, one reason it has prospered.

I write this post mostly to record how depressed I am that software guruism of such low quality seems to be so popular.

If you want to wash the ugly taste of Martin out of your mouth, I recommend this interview with Leslie Lamport. Ruby hackers have esprit de corps and throw big buzzworthy conferences, whereas Lamport is merely a genius. Guess what the kids end up learning today.


*If you care at all, his entire argument can be summed up in a few sentences as follows:

  • Smalltalk is much more expressive than C++.
  • However, Smalltalk does not "punish you for making a mess"; i.e. you can easily write software that is intricate to the point of being incomprehensible. This is why Smalltalk failed.
  • Test-driven development can provide the discipline which stops the same thing from happening to Ruby.

As I've noted, I think this argument's wrong in so many different ways that it exhausts me mentally even to try to enumerate them all. But just as one angle of attack, note that of the suggested causal factor is false of many failed languages, and true of several popular ones. Forget about correlation not implying causation; I claim that in this case even the correlation is low. Furthermore, long-lasting popularity is so rare for programming languages that it is a fool's game to talk about why unpopular languages never became popular; it's much more fruitful to seek the very rare combination of characteristics common to successful languages.


p.s. UPDATE 8pm: What a relief, lots of other people thought the talk was b.s. too. See J. Robertson of Cincom

UPDATE 2017-10-06: Fixed some linkrot.