Time To Market (for your Domain Specific Language)

“The biggest advantage I can see is […] that the Java language can be extended along certain lines without waiting for the fairly long release cycle to approve and produce something new. It should also take some pressure off the compiler writers, in that some features which previously would require a language change can, in some fashion, be accomplished with closures.”

Patrick Wright on artima

…so keyword arguments and map constructor syntax will be next?

Anonymity

Talking about anonymous abstract concepts in the “ProgLang” category, I noticed that the “axel” concept remains curiously anonymous. No reason, really, just oversight. So here’s how my MacBook sees me.

Note that some people go much further with iSight / Photo Booth…

P.S.: If your iSight stops working and goes all green, as mine did after coming back from repairs (sic), try this and then this – did it for me.

Higher-Order Functions and the Object-Oriented Paradigm

Wow, if I had known my previous post would be read with such scrutiny, I might have left it to ripe a bit longer. I’m really happy to have helped ignite such a balanced and informed discussion!

Originally I intended to post the following as a comment on Reginald’s blog, but I was unable to keep my prose down to a reasonable size… blogs are not the perfect medium for a discussion, but here we go.

The point I tried to make about type checking is that the type checker has no meaningful way to report typing problems if you don’t give him the names, but just a knot of function types. Similarly, if everything is just a list (as in ideal Lisp), the runtime errors can speak of nothing but cons cells.

Reginald, I’m glad you think that the importance of naming things is “obvious” – some programmers appear to think otherwise. Someone might find the task of making up good names unnecessary, or challenging, so they skip it where possible (especially when working in a haste, especially those with a maths/physics background who have learned to deal with pure structure). I consider this bad practice for software, and therefore would not want a programming language to actively encourage conceptual anonymity.

I probably mistook the point of your original post because you set out to answer the question “why should I care about closures, as Java programmer”, but described closures from a purely functional perspective. I believe Java programmers need to care about closures not because the functional paradigm is great, but because of how closures enrich OO programming.

Haskell and ML are much better at domain modelling than Scheme, because of their type system (which is notably absent in Ruby) We can assume “functional-style” programming in Ruby resembles Scheme more than ML, so that’s what I was relating to, given that your examples were using Ruby.

Closures in Smalltalk were originally not full static closures – they were used mostly for control structures and iteration. The full power of closures (as in Scheme etc.) was only added in a later iteration. Which seems to indicate to me that their full power was not required for the “prime use cases” of OO programming – you could still refactor to class-based objects when you needed more.

The Undo/Redo stack is a perfect example of something that should NOT be done using closures. Because each command is not one, but two closures (one for Redo, one for Undo), so which is your object identity?; a command may have a name you want to present to the user (“Undo move” vs. “Undo delete”); and when your software is supposed to persist a command log, or merge commands executed by different users on the same document, you will need a much deeper analysis (instead of just execution) of the commands. Of course you can try to refactor at some point, but searching for all usages and implementations of “Closure.apply” will not produce very meaningful results.

Transactions are another example of more than just a closure – they’ll have an isolation level, a name, an identifier,… Obtaining these property values certainly requires a broader interface than closure.apply(), or another object to wrap the closure, again splitting up object identity. What transactions do have is a Single Abstract Method – did I mention I like the CICE proposal?

So I actually would like a language that is “opinionated” in the sense that it gives guidance. Would you really want to program in an opinion-less language, if such a thing can be imagined at all? How would two pieces of code in that language every fit together? In the Tycoon libraries, each data structure was implemented three times, once functional, once imperative and once OO. Seems wasteful, doesn’t it? All language designs I like express the opinion that “goto” should be rarely used. Don’t you think? In a similar vein, I would like a language to express that most things ought to be named and related to domain concepts.

From Functional to Object-Oriented Programming

The Java blogosphere is currently discovering or introducing to the uninitiated the benefits of closures. To me, posts like Reginald’s seem to present closures as an advance from OO. This is kind of strange, given that the historical order is exactly the other way round!

When I started digging into OO languages in the 90s, I had already spent some time with Scheme and Tycoon (a language based on Luca Cardelli‘s Quest), all of them higher-order functional-imperative programming languages. I did some non-trivial compiler programming in both languages, and it certainly was fun, in a way similar to solving math riddles.

I learned that OO was great because it names things. OO allows a traceable connection between the conceptual design level and the implementation level. Concepts have names, so you can talk about them, between programmers and architects. The promise of OO was to replace the dazzling complexity (and intellectual challenge) of functional programming with something more manageable.

Language is not understood best when you have removed as much as possible. Would you rather read a novel, or an algebra textbook? Just imagine taking your green, yellow and red pen and marking up a book by Neal Stephenson.

Conciseness comes at a price: The more compressed your code, the harder it is to understand what the consequence of some change would be. If you have left out everything you do not need for your current goal, what if the goal moves? If (e.g.) you find that what was once a closure should now be a class, e.g. because some code wants to inspect it instead of just running it, you’ll be crying for another super-advanced refactoring IDE.

“Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it?” (Kernighan)

Higher-higher-order functions and inferred types, or lists of lists of pairs whose cdr happens to represent some concept (except when it represents another concept) will all give you that occasional “ouch, there’s a error message, but I don’t think there should be!” The code looks fine, so why does the type checker not like it? (it probably took something you wrote, took it all wrong, drew impressive conclusions and is now reporting a problem at a completely different place). The program state and the code both look fine, but they differ in the level of nesting of some unnamed construct (e.g. a closure or a list where a value was expected).

I strongly associate higher-order functional programming with long stretches of uninterrupted concentrated programming work, and single-person projects. In contrast, OO gives you a pragmatic, shallow paradigm for making software intelligible and available for cooperation.

Closures can be a nice tool for creating your own DSL, to make your code get closer to the design model. But closures can also take you further away from the design model, by creating constructs that only make sense in the abstract.

Object-oriented programming was introduced to fill a need not satisfied by functional and imperative languages. Remember: Going from functional to OO is an advance.