Skip to main content
Tim DisneyTim Disney

Link roundup

Crista Lopes bemoans the state of PL research with good responses from Matthias Felleisen and LtU (read moar Kuhn!).

SQLite compiled to JavaScript via Emscripten

Mark Lynas seems to think we can get the entire world out of poverty without breaking the planetary boundaries (think carbon, biodiversity, land use, etc.) by 2050. Cute.

Game of Thrones is available at long last online but who's complaining.

The NSA is apparently building a massive data center in Utah. This doesn't concern me at all.


Occupying Language Design at POPL

At POPL last week I gave a student lightning talk on our Virtual Values paper. The format was four minutes with the slides advancing every 20 seconds. Very difficult to communicate the important idea in so short a time but it was really fun and I think turned out pretty well.

Check out the slides if you're interested. I added notes on each slide that corresponded more or less to what I was saying.


Updates to contracts.coffee

An update to contracts.coffee (0.2.0) is now up on npm. I've fixed up a few bugs since the intial release and it's now based on the latest CoffeeScript (1.2.0) but the big update is a rework of how modules are handled.

Before this update we were handling module blame tracking by forcing the programmer to call .use() before a contracted value could be used. This did the work of figuring out who the server and client module.

This was an awkward way to enforce a module pattern since not only do you have to write more code but it also means you have to know which values in a module have a contract. This breaks abstraction which is bad.

So with this latest update we're completely dropping .use(). How we keep tack of the modules without it depends on whether you are using node.js or a browser.

If you are using node.js then the wiring is handled automatically by wrapping the require function and exports object. If you put a contract on an export value the correct server and client module names are recorded.

# file Math.coffee exports.square :: (Num) -> Pos exports.square = (x) -> x * x

#####

# file Main.coffee {square} = require './Math'

# vioation blaming Main.coffee square "a string"

You can also put a contract on a value that isn't on the exports object (for use inside the module), but the module name might get confusing since it's just the file name with "(value)" or "(caller)" appened. I will look at adding something like Racket's nested boundaries to clean this up at some point.

If you're using the browser, things are a bit more complicated. Since the browser environment doesn't currently have a standard way to do modules, we're stuck doing the wiring by hand. Details are in the documentation but the basic idea is that the library now provides Contracts.exports and Contracts.use which are used to construct contract aware modules.

Contracts.exports creates and names an exports object:

# Math.coffee

# create and name the exports object exports = Contracts.exports "Math"

exports.square :: (Num) -> Pos exports.square = (x) -> x * x

# put the exports object on the global object # for other modules to see and use window.Math = exports

And Contracts.use pulls in a module and names the user of the module.

# Main.coffee {square} = Contracts.use window.Math, "Main"

square 4 # 16 square "a string" # Contract Violation...blaming Main

I'll look at ways to automate this more in future updates.


Performance of contracts.coffee

I've been meaning to get around to running some performance benchmarks on contracts.coffee, but I recently learned a valuable lesson: let the internet do your work for you! :-)

I woke up this morning to find @paulmillr had put together a nice performance benchmark of contracts.coffee.

Check it out for all the gory details but suffice it to say contracts makes things...slow. This is about what I'd expected since in addition to running the actual contract check we must wrap the contracted functions/objects in a Proxy which runs handlers for each function call or property set/get. Lots of stuff is in the way of the running code.

So does the slow performance of contracts make them unusable? Not necessarily. First off, the contracts.coffee compiler can emit JavaScript with contracts completely disabled. So, you can have a "slow" testing/development build with contracts enabled to help track down bugs and a production build with contracts disabled and no slowdown.

In addition, most code is IO bound not CPU bound. So if you want contracts enabled everywhere but still care about performance, be smart about where you apply them. Put them on module boundaries, but don't put them on tight loops for example.

In sum, contracts are another tool in the software engineer's toolbox that have advantages (bug squashing) and disadvantages (performance slowdowns when enabled). Use them wisely.


Contracts.coffee Works In Node.js!

Contracts.coffee now works in node.js! V8 (the JavaScript engine used by node) has recently added support for Proxies which contracts.coffee requires.

You'll need a bleeding-edge version of node to get it running. Try either master (unstable) or 0.5.7. Build instructions are here.

Proxies are hidden behind a command line flag in V8 so you'll also need to supply --harmony_proxies to node when calling the compiler:

node --harmony_proxies bin/coffee -CL test.coffee

There are almost certainly node-specific bugs in contracts.coffee so don't trust it with anything important yet. You can get started playing though!

Report any bugs you run into on the issue tracker.


Duck-Typing Invariants In contracts.coffee

So the response I've been getting for contracts.coffee has been absolutely incredible! There's been tons of positive feedback and some really great excitement about the project.

I've also heard a few worries that contracts are too much like static types and might not be such a good fit for a dynamic language like CoffeeScript or JavaScript. Now, I don't want to get into a huge debate over the merits of static vs. dynamic typing (that way leads to madness and holy wars!) but I would like to clarify a few points and show that contracts actually fit quite nicely into the dynamic ethos of CoffeeScript/JavaScript.

In dynamic languages like CoffeeScript and JavaScript you'll often hear about duck-typing where we don't care about the "type" of an object, just the stuff on the object we actually need to use. So the classic example is a "file-like" object where all we care about are the few properties the code actually uses (like open, read, close, etc.). As long as the properties exist we're good. If a property don't exist and we try to use it, just throw an exception so we can track down the bug.

Contracts allow us to extend this concept quite a lot without sacrificing the awesome flexibility we dynamic language users love about duck-typing. To start out, let's consider the simple case of a missing property. Let's first define a contract for a binary tree:

# A basic binary tree BinaryTree = ?(Null or { node: Num left: Self or Null right: Self or Null })

Pretty simple, a binary tree is either null or has a node and two children that are also binary trees. A function can now say it expects a BinaryTree:

f :: (BinaryTree) -> ... f = (tree) -> n = tree.node ...

And if we call f with something that isn't quite a binary tree:

broken_tree = nodee: 42 # misspelled! right: null left: null

f broken_tree

We get a very descriptive error message:

Contract violation: expected <{node: Num, left: self or Null,
                                right: self or Null}>,
  actual: "[missing property: node]"
Value guarded in: coffee-script.js:53
  -- blame is on: coffee-script.js:56
Parent contracts:
{node: Num, left: self or Null, right: self or Null}
Null or {node: Num, left: self or Null, righ : self or Null}
(Null or {node: Num, left: self or Null, right: self or Null})
  -> any

Now we're already winning since the error message is triggered as soon as the function is called with an object that is missing the required properties. If we weren't using contracts, the variable n in the example above would get the value undefined which might not surface as an obvious problem until much later (if ever!).

We're also not losing any of the flexibility of duck-typing since contracts allow us to specify just the object properties the function needs in order to work properly. We're just being explicit about how our ducks should quack!

In addition to an early failure, we get lots of information in the error message about what was missing, which contract was violated, and which module was to blame (a powerful notion I explain a little here but which really deserves a future blog post).

But we're just getting warmed up :)

Contracts on objects can also have arbitrary invariants that get checked whenever properties are modified. So we can have a contract for a binary search tree:

# A binary search tree is a binary tree where each node is # greater than the left child but less than the right child BinarySearchTree = ?(Null or { node: Num left: Self or Null right: Self or Null | invariant: -> (@.node >= @.left.node) and (@.node < @.right.node) })

And a red-black tree:

# A red-black tree is a binary search tree # that keeps its balance RedBlackTree = ?(Null or { node: Num color: Str left: Self or Null right: Self or Null | invariant: -> (@.color is "red" or @.color is "black") and (if @.color is "red" (@.left.color is "black" and @.right.color is "black") else true ) and (@.node >= @.left.node) and (@.node < @.right.node) })

Note that our contract for a red-black tree is exactly the same as a binary search tree with the addition of the color property and some related invariants. We have a kind of subtyping going on here: a function that expects a binary search tree will also work with a red-black tree but not vica versa.

Now our functions can "duck-type" the invariants on the objects they accept:

takesBST :: (BinarySearchTree) -> Any takesBST = (bst) -> ...

takesRedBlack :: (RedBlackTree) -> Any takesRedBlack = (rbTree) -> ...

bst = makeBinarySearchTree() rb = makeRedBlackTree()

takesBST bst # works fine takesBST rb # works fine

takesRedBlack rb # works fine takesRedBlack bst # might fail if the full # red-black invariants don't hold!

These functions not only specify that they require certain properties but also that certain invariants must hold. This is really powerful! The function that only requires the behavior of a binary search tree can accept a red-black tree just fine and the function that requires the behavior of a red-black tree but is given just a binary search tree will fail when the invariants are violated (just as we want it to).

So, contracts allow us to be explicit and fail early when things go wrong while still giving us the flexibility of duck-typing. And they work for both "missing-property" kinds of failures along with a more general "failed invariant".


Contracts.coffee - Contracts for JavaScript and CoffeeScript

This summer I've been working at Mozilla looking at bringing the awesomeness that is contracts to JavaScript. If you aren't familiar with contracts, think of them as super powerful asserts.

Why contracts? Because they allow us to build better software! They allow us to express invariants (things that will always be true about our code) in JavaScript about JavaScript and check at runtime that these invariants hold. And when things break (like they always do) we get a precise error message pin-pointing the part of our code the broke the contract.

Contracts in programming languages were first popularized in the language Eiffel. In fact, the people behind Eiffel promoted an entire design methodology centered around contracts (called, appropriately enough, Design by Contractâ„¢) that encouraged thinking about invariants and interfaces between software component boundaries.

So if contracts are so great why don't we see them in JavaScript? Well, for the most part, the languages that have supported contracts in the past all share an important characteristic...no lambdas. Or more specifically in Java and Eiffel functions are not first class (you can't pass a function in a method call). Traditional contract systems fall down in a higher order setting (how do you check a function argument?).

Until, that is, the scheme people (err...I mean Racket people) figured out what to do a few years ago. Now, Racket has a very nice contract system.

But we haven't seen anything comparable to Racket's contracts in JavaScript so far. So this summer I looked into taking the work that was done in Racket and trying to fit it into JavaScript. As you probably know, JavaScript has a bit of scheme in it (just confused by some C/Java syntax).

The result of this exploration is a JavaScript libarary called contracts.js and a fork of the CoffeeScript compiler (which translates CoffeeScript directly to JavaScript) called contracts.coffee. The JavaScript library gives us the ability to apply contracts to our code and the CoffeeScript extension gives us some really pretty syntax.

So what does it all look like?

Here's some CoffeeScript code with contracts:

id :: (Num) -> Num id = (x) -> x

And the JavaScript translation:

var id = guard(
     fun(Num, Num),
     function(x) { return x; })

This code takes the identity function and wraps it in a function contract. Now every time id is called the contract library first checks that the argument being passed in satisfies the Num contract (which checks the the value is a number) and that the result of id also satisfies Num. If any of these checks fail, an error is thrown. For example:

id("string")
Error: Contract violation: expected <Number>, actual: "string"
Value guarded in: id_module.js:42
  -- blame is on: client_code.js:104
Parent contracts: (Number) -> Number

Pretty nifty right?

We can also have contracts on objects:

person :: name: Str age: Num person = name: "Bertrand Meyer" age: 42

And arrays:

loc :: [...Num] loc = [99332, 23452, 123, 2, 5000]

And various combinations thereof:

average :: ({name: Str, age: Num}, [...Num]) -> Str average = (person, loc) -> sum = loc.reduce (s1, s2) -> s1 + s2 "#{person.name} wrote on average #{sum / loc.length} lines of code."

You can find documentation, install instructions, and a bunch more examples for contracts.coffee at its website. Docs for the underlying contracts.js library is coming soon but for now just check out the github page.

This is still very much a work in progress and I would love feedback. Let me know if you find it useful!