Rusty's Interface Simplicity Spectrum
Martin Pool writes yet another excellent blog entry, this time about Rusty on Interface Simplicity. His OLS 2003 keynote had an “interface simplicity spectrum”, which is so good, Martin reproduced it in his blog, and I’m going to reproduce it in mine, for my own reference:
- Compiler/linker won’t let you get it wrong.
- Compiler will warn if you get it wrong.
- The simplest use is the correct one.
- The name tells you how to use it.
- Do it right or it will break at runtime.
- Follow common convention and you’ll get it right.
- Read the documentation and you’ll get it right.
- Read the implementation and you’ll get it right.
- Read the correct mailing list thread and you’ll get it right.
- Read the documentation and you’ll get it wrong.
- Follow common convention and you’ll get it wrong.
- Do it right and it will break at runtime.
- The name tells you how not to use it.
- The obvious use is wrong.
- Compiler will warn if you get it right.
- Compiler won’t let you get it right.
- It’s impossible to get right.
(Obligatory Haskell plug: a nice one-line summary of the Haskell language is that just using it for your code, puts you at #1 on that spectrum an incredible amount of the time.)
Functional Programming Koans
Doug Bagley’s most excellenté functional programming koans, courtesy of Sean Seefried. Here’s one example:
The Koan of Lazy Evaluation: Michel Mauny was giving a guest lecture to new computer science students. After the students were seated, Michel pronounced “Today’s lecture will be about Lazy Evaluation”, he paused for a moment then concluded with, “Are there any questions?”
Unused parameters in gcc
Martin Pool has a really nice blog entry on how to use -Wall
to turn on all warnings in gcc, and stop it from complaining when you have unused parameters. This is quite a common scenario when you’re using callbacks (a.k.a. delegate or visitor methods).
Boo: A New CLR Language
Lambda the Ultimate has a story on a new CLR (.NET) language named Boo. Ian Bicking’s comparison of Boo vs Python is a nice, succinct summary of it. Looks quite interesting: type inference, duck typing, macros, and string interpolation. Seems that the CLR does seem to be breeding all sorts of new languages …
Imperative Code as Streams
In imperative languages, you usually get a new random number by calling a function (such as C’s rand(3)
) when you need a new one. You can do this in a functional language like Haskell too, but then you’re forced into an imperative style, which isn’t very functional. (An imperative style would be required because generating a new random number depends on the current state of the random number generator.) You can keep a functional programming style by having a random number generator produce a (lazy) list of numbers, rather than a single number: any code which wants a random numbers simply pulls the next one out of the list. I posted some example code to the haskell-cafe mailing list recently to demonstrate this, in answer to a Haskell newcomer’s post. Lazy lists are often also called streams.
Normally, monads are used to encapsulate state changes in Haskell in a purely functional manner, but you can use streams too: any state changes which occur can be represented with new list elements. It’s no coincidence that streams are monads: they’re powerful enough to sequence non-deterministic operations. The Haskell Ports Library gives you even more convenience when working with streams by modelling time as a list, and the awesome iHaskell and Fudgets libraries for Haskell manage to model an entire GUI in a purely functional manner. Just to show that this is also has a practical benefit, the Fudgets code examples show how succinct writing GUI code can be. The Fudgets thesis is a great introduction and explanation to how it all works.
Closely related is the newer concept of arrows, which provide a formal framework to reason about stream-based (and also various other non-stream-based) computations. Anyone up for writing a Haskell library to interface to the gstreamer media framework as an arrow?
Me on Xoltar on Static Typing
Bryn Keller (a.k.a. Xoltar) takes on Bruce Eckel’s comments about Python and static typing, and does a pretty good job at poking all the holes in Eckel’s arguments while remaining objective. Worth a read, especially if you’re wondering what all the hoopla is about Haskell and O’Caml’s type systems.
My Comments
Bryn comments toward the end of his article about how duck typing can lead to ‘dangerous’ situations. He uses the example of a method named draw
, which has different semantics for the Gunslinger
class (where draw
means ‘Bang!’) vs a Artist
class (where draw
means ‘paint’). While it’s possible to have such name clashes with different semantics, in reality I don’t think it’s a big problem: certainly one not worth spending a few paragraphs on in an article. (When would this situation ever crop up, for example?)
He points out that in the Nice language, you can write a class, and make them part of the interface later. In his words: “We also got additional power in the bargain, because now we can selectively bless any class we like into the Speaker interface, without including classes we don’t want - we can ensure that our Artist doesn’t end up in a gunfight by mistake!”. In languages such as Java or C++, you must declare that a class implements an interface when you write the class: you cannot write a class and declare later that it implements the interface. It is very cool to program in a language which enables you to separate the code you write, from declaring how that code is used as part of your whole system design. Some other examples of this feature in other languages are:
- Haskell, which enables you to declare a type class to capture common functionality provided by different functions. So, you could write a Haskell module which provides a new Hashtable data type, and another Haskell module to provide a new balanced tree data type. You can then later write a type class to capture operations common to such colletion/aggregate types, by writing a new type class that declare type signatures for functions such as inserting objects into the collection, or retrieving objects from the collection. Note that you could have completely different interfaces to the hashtable/tree classes with completely different type signatures: the type class performs the ‘glue’ code necessary to provide one clean, consistent interface to both of them. (Plus, the very small glue code required to do that will be optimised away by any optimising Haskell compiler, such as GHC.) This is the same idea as Nice’s separation of code declaration vs interface declaration, though type classes are a far more powerful and generic concept.
- Objective-C’s categories, which enable you to add new methods to existing classes. You don’t like it how the
NSFileHandle
class doesn’t have a method to create a new temporary file and return you a file descriptor for it? No problem, just add your own method to do that to the class — no subclassing necessary. Categories are possibly the greatest thing I miss about Objective-C when I use any other language (Haskell included: it would be really cool to be able to extend type classes by adding new methods to them!). C# has a similar feature named partial types, although it’s nowhere near as elegant as categories. Perl 6 takes this idea even further than Objective-C does: it differentiates between open classes, which can have methods added to them, and closed classes, which can’t. The clever bit is that all classes are open by default, but any users of that class will close the class unless it’s specifically declared open. This is really smart because it means that you can have the same flexibility that open classes give you, but you gain all the optimisation opportunities that come with closed classes, such as performing static dispatch rather than dynamic dispatch on a function call, which opens up a whole new set of optimisations that weren’t previously possible, such as inlining.
One of the points of Bryn’s article seems to be that static typing detects different errors from unit tests: while this is true, I’d phrase this a different way. One benefit of unit testing is that it helps you develop your code faster because unit tests enable your code to be more robust as you develop it, saving you from hunting down those stupid bugs later on. Modern static type systems give you different test coverage, and I think they speed up your development even more, because they often pick up a lot more errors than unit tests do. If you’re a Perl programmer, the use strict;
pragma that Perl has basically turns on static type checking. Think about how many bugs you’ve found thanks to its warnings and errors, and imagine how much of a nightmare it’d be if you didn’t have that facility at all. Now think about extending Perl’s simple type system (which is limited to only type checking of scalars/arrays/hashes), so that types are pervasive in your program design that enable far better coverage by the type checker, and you’ll hopefully have some idea of what I’m talking about.
He remarks right at the end of his article that “We need both strong testing and strong typing” — I think he means static typing, not strong typing, considering that was what his entire article was about :). Mind you, static and strong typing seems to be confused quite easily: even Guido van Rossum confuses strong typing with static typing. I personally find it a bit worrying that the designer of such a popular (and great!) language gets it wrong, but hey, nobody’s perfect.
Bryn, I think, doesn’t point out the biggest benefit of modern static typing systems: it saves you time because so often, when that anal type checker finally does let your program compile, it just works a really surprisingly large amount of the time. (This is closely related to the increase in productivity that I discussed above, but it’s not quite the same thing.) It’s downright unnerving just how many times your program performs correctly: one thread on the cvs-ghc mailing list gives an anecdote, where most of the Glasgow Haskell Compiler back-end was ripped out and re-written (14000 lines of code!), and the PowerPC code generator worked first-go. I’m yet to nail down whether this phenomenon is only due to the advanced type systems alone, or whether it’s a combination of the powerful type system and a (purely?) functional programming style; I suspect it’s the combination of the two. Programs are much easier to reason about when state changes are made explicit.
6-Star Smart Playlists in iTunes
iTunes is nice and all, but I wish you could rank a song between 0-6 stars rather than 0-5 stars. That way, you can classify 0-star songs as unrated, and have 5 stars leftover for your own classification, rather than 4, which may be a bit too restrictive. Well, you can do this pretty easily for purposes of including it in a smart playlist, which is all I wanted to do.
How to do it? Easy:
- Rate all your 6-star songs as 5-star, so they’ll be included in any matches that would normally include 5-star songs.
- Add the text “6-star” to the comment of any of the songs you want to rate as 6-star.
- Make a new Smart Playlist, and include the “6-star” text as part of the criteria for the playlist.
That’s it. You can obviously expand the scheme to 69 stars if you want, but 6 is enough for me.
Beyond C, C++, Perl and Python
Abstract
As a Linux user or developer, you probably know a few programming and scripting languages: shell scripting, Perl perhaps, Python, C or C++, and maybe Java or XSLT. Once you’ve learnt one systems language or one scripting language, you’ve learnt them all, right? Especially because of that “Turing-complete” thing …
In this talk, I’ll explore the research and developments that have happened outside of mainstream programming languages in the past decade, in languages such as Objective-C, Haskell, O’Caml, and Nemerle. The scope of the talk is broad: I’ll touch on many topics, such as meta-programming, generics, type systems, and proof-carrying code, without going too in-depth into any of them. (Believe me, you don’t want to hear me talk for seventeen hours about type systems.) Most of the topics covered (such as meta-programming) are not language-specific, and can be directly applied to your own work, increasing your own programming expertise and repertoire of techniques.
Download
Slides: Adobe Acrobat PDF