Ask a physicist and you’ll get the answer to a well-known riddle. “What’s Nu?,” it’s “c over lambda”. Physicists use the Greek letter nu to represent the frequency of light, which can be expressed as its speed c divided by its wavelength lambda.
Nu also is the name I chose for a project that relates a different C to a different lambda. Nu is a new programming language that binds the expressive power of Lisp to the pervasiveness and machine-level efficiency of C by building on the power and flexibility of Objective-C.
A major goal of Nu was to make it easier to build and reuse software components. Consistently with that, Nu was built from many preexisting components and many well-developed ideas. There’s not much that’s new about Nu except for its particular combination of recycled parts.
Nu is object-oriented and functional. It is written in Lisp-like S-expressions but conforms to no preexisting Lisp standard. Instead, Nu was designed to follow Yukihiro Matsumoto’s “Principle of Least Surprise” while staying tightly integrated with C via the Objective-C runtime and object model.
Objective-C is an object-oriented extension of C that provides powerful messaging primitives, deep runtime introspection, and dynamic binding, all important tools for bridging to dynamic languages. From that, Objective-C has been bridged to many dynamic languages: Python, Ruby, Perl, Scheme, and many others. It has also been used to build at least one completely new scripting language, Philippe Mougin’s F-Script.
Nu is written in Objective-C, and Nu is designed to allow deep interaction with Objective-C programs. As a result, Nu has deep access to its own implementation. That gives its users an unusual ability to explore and understand Nu. Where there is understanding, there are few surprises.
Inspired by Alexander Burger’s Pico Lisp, I decided to write Nu in early 2007. Previously I had been involved with two projects that bridged Ruby and Objective-C: first RubyCocoa, an open-source bridge created by Hisa Fujimoto and now actively supported by Apple, and then RubyObjC, a completely new bridge that I wrote to address reliability issues with RubyCocoa and to go deeper into the Objective-C runtime. In both projects, I was attempting to link the expressiveness of Ruby with the efficiency of C by building on Objective-C.
Why not Ruby?
Of all the existing dynamic languages, Ruby seems like the best choice to bridge to Objective-C. Both are children of C and Smalltalk. From Smalltalk they inherited very similar object models, and both languages are layered on C. That suggests a natural combination: Ruby for high-level programming and scripting and Objective-C for higher-performance C subsystems.
But because they developed independently, Ruby and Objective-C each has its own set of essential and supporting elements, and like cantankerous newlyweds, each prefers its own way of doing things. Here are some examples.
- Ruby and Objective-C have completely different and inconsistent syntaxes for message sending. Along with many other language bridges, the Ruby to Objective-C bridges force an awkward solution on Ruby programmers for the sake of predictability. This is a minor but annoying problem that conveniently disappears when we switch to a syntax of S-expressions.
- Ruby and Objective-C have completely different representations of standard data elements such as strings, numbers, arrays, hashes, and exceptions. Bridges must either automatically convert values when they cross the bridge (which is expensive) or try to teach the types of one language to masquerade as the types of the other. Deceptively, this sometimes works, but it is nearly impossible to fully hide this problem.
- Ruby and Objective-C have large and overlapping libraries. It’s tempting to believe that combining them provides the best of both, but in practice a developer usually has to favor one set of libraries over another, and like the standard elements, library objects such as files, dates, and ranges must be converted whenever they cross the bridge.
- Ruby and Objective-C store objects differently. As a result, objects with data in both languages (such as instances of Ruby classes derived from Objective-C classes) must be stored in two places and both parts must be correctly maintained.
- Ruby and Objective-C have completely different memory management schemes. Ruby is garbage collected and Objective-C is typically reference counted. An important challenge for a Ruby bridge is to make sure that the Ruby garbage collector never deletes objects that are needed by Objective-C instances. Mistakes in memory management usually lead to sudden and hard-to-debug crashes.
- The Ruby and Objective-C threading models are different and completely incompatible. In a multithreaded application, it is impossible to use Ruby in any thread but the main application thread, and even this requires a patch to the Ruby language implementation. With multicore systems all around us, this is simply unacceptable.
- Ruby and Objective-C libraries occasionally use the same names to represent different methods. To resolve these conflicts, one side (usually the Ruby side) must convert any conflicted names into something different, typically by adding a prefix. This is workable but can lead to surprising errors.
A good bridge must correctly and reliably address all of these issues, but no bridge can hide everything. For mixed language programming, these inconsistencies are a fact of life, and this is for a well-matched pair of languages. The problems of binding Objective-C to any other scripting language are worse.
Nu is my solution to these problems. Instead of grafting two mature and overlapping language implementations together, I wrote Nu on, with, and for Objective-C. Instead of being problems to be bridged, the rich set of Objective-C classes became the building blocks of Nu.
The Objective-C object model is the Nu object model. Nu directly uses the Objective-C runtime to store its class descriptions. Nu code can be used to create new classes and to add class methods, instance methods, and instance variables to existing classes. Like Objective-C, Nu uses Smalltalk-style message sending, and like in Smalltalk, everything in Nu is an object. Standard Objective-C types such as NSString, NSNumber, NSArray, NSDictionary, and NSException are used throughout, and Nu provides some new classes and extensions to existing classes to make it easier to program in both Nu and Objective-C.
Nu is interpreted; the interpreter is built as a framework that can be imported into any Objective-C application. The Nu framework includes a built-in console that can be easily activated to allow developers to directly interact with their Cocoa applications using Nu.
Nu also borrows some tricks from Ruby that make its code more readable and concise. Here documents can be used to declare multiline string constants. Strings can contain interpolated Nu expressions. Names that begin with ”$” have global scope; names beginning with ”@” denote instance variables. For experienced Lisp programmers, the ”__” prefix is used to declare generated symbols, which are important tools for safe programming with macros.
I’m still working on Nu, but I’ve already used it to build a few things, including the program that serves and manages this blog. In future posts I’ll describe that in more detail and share more about Nu.
So that’s Nu. A new language that’s not so new. It’s just an evolutionary mix of recycled ideas, but what else are revolutions made of?