Brian York's Life
Syndicate this site (XML, http link)
Syndicate this site (XML, feed link)
E-mail Me
A Nu way of doing things
Written on March 23, 2008
Yes, I almost never post at the moment. But right now I’ve just had enough of writing my thesis, and I want to write something else, like a journal entry. So here we are. I expect that I’ll start with a few more general ideas, and then move on to justify the rather bad pun in my title. So, life first, code second (not that that’s the way I actually live, but it’s a good way to organize a journal entry.)
So, what’s going on with my life at the moment (other than writing my thesis of course)? Not too much, I’m afraid. I am making progress on my thesis though, so that’s definitely good news. Three of the five chapters either done or mostly one, and the fourth started, and I’m on target to defend at the end of July. And, my committee has been convinced to continue my funding through the end of August (for those who know something about how things have been going, this counts as a major victory).
Even with my thesis work though, I’m still learning new things. For example, a couple of weeks ago I discovered an excellent tip for those of you who cook. When one is trying to cook something (even if it’s just a simple “dump onions, vegetables, and maybe meat into a frying pan, cook it, and serve with rice, noodles, potatoes, whatever”), it is important to put the frying pan on the stove before turning the stove on, and vitally important to put the frying pan on the stove before adding olive oil and starting to cook your onions. Otherwise, the process becomes a bit messy. Or so it seems to me. Theoretically at least. Because, after all, I haven’t actually done anything like that of course.
Moving on now…
There’s an old physics joke where, when someone asks you “What’s new?” you reply “c/λ.” (to ruin it completely for those who haven’t heard it, physicists use the greek letter ν (“nu”) to represent frequency, and c to represent the speed of a wave (and λ (“lambda”) to represent the wavelength of a wave). The wave equation is c = λ ν, so by transformation ν = c/λ, and thus “What’s new?” may be interpreted as “What’s ν?”, and answered appropriately). In my spare time (ok, ok, I don’t actually have spare time, so this is the time during which I can’t write coherently anymore, but my mind is active enough that I need to do something other than reading) I’ve been learning a new programming/scripting language (mostly for MacOS X, but also now usable for Linux), known as “Nu”. Nu is essentially a lisp-based Objective-C interpreter (hence the same — this is really c/λ (if you don’t know the relationship between Lisp and λ, this page will serve as a useful primer)).
So, why do this in the first place? Well, Lisp is an extremely powerful language, in part due to its format (s-expressions make it trivial to treat code as data, which in turn makes it trivial to do some very clever things with your code), but it has a few weaknesses. One of Lisp’s weaknesses is its lack of libraries (while I have learned some Common Lisp (ok, another of Lisp’s weaknesses is that Common Lisp was not really put together in an elegant way, at least as far as I can see), I would use Python instead of Lisp for many purposes just because Python actually has a bunch of libraries that let me not have to worry about writing my own functions to process text, or access a network, or build a decent GUI application, or whatever). MacOS, however, has an incredible number of very useful libraries, mostly written in Objective-C (a combination of useful utility functions and excellent object-oriented GUI-building tools, known as “Cocoa”). Nu, by acting as (sort-of) an Objective-C interpreter, gets most of these libraries essentially “for free”.
Nu also has advantages over many existing Cocoa bridges, including PyObjC and RubyCocoa (etc.) in that it isn’t really a bridge, it’s more a different way of writing Objective-C code. A Nu class is an Objective-C class, and Nu code can be compiled into Objective-C code (or libraries, or frameworks) with almost no overhead.
Objective-C
Now, Objective-C itself has its good points and bad points. It’s very close to C (classic K&R C no less), which may be either good or bad depending on how you feel about C. It takes a lot of its object model (and syntax) from SmallTalk, which again may be either good or bad depending on how you look at it. Objective-C tends to do a lot of things at runtime that C++ (for example) would do at compile time. For example (to quote Andrew M. Duncan’s “Objective-C Pocket Reference”)
Objective-C differs from C++, another object-oriented extension of C, by deferring decisions until runtime that C++ would make at compile time. Objective-C is distinguished by the following key features:
- Dynamic dispatch
- Dynamic typing
- Dynamic loading
The end result of all of this is that, when you send a message to an Objective-C object [myObject doSomething:withParameter], the code that gets called by the message isn’t decided until runtime, and depends on the type of the message receiver (which doesn’t even need to be specified at compile time). For example, if you were writing a paint program, you could say:
id myShape;
myShape = [[shapeSelect alloc] init];
[myShape display];
without having to worry about what type of shape was selected by shapeSelect (presumably a routine that waits until the user selects a shape from the drawing palette and then returns the type of shape that they selected). As long as every shape can receive a display message, you’re fine (id is the Objective-C type of a generic object — an id is always a class of some sort, but may be any class). Objective-C also does dynamic loading, so any libraries that your program uses won’t actually be loaded until you need them (which can make your program more resource efficient).
Nu
Having given you a (very) quick introduction to Objective-C, I’m now going to very briefly describe how Nu works. I’ll be using “nush” (essentially a Nu interpreter which lets you use Nu as a scripting language) as my environment (if it actually matters). So, in nush, I could write a simple program to load a (hard-coded) file, and output the number of characters in each line (all of the classes I’ll be using are Objective-C classes, so you can already begin to see the advantages of Nu’s close relationship with Objective-C):
(set input ((NSString stringWithContentsOfFile:"/Users/shared/sharedfile.txt") componentsSeparatedByString:"\n"))
(set output (NSFileHandle fileHandleWithStandardOutput))
(set i 0)
(while (< i (input count))
(output writeData:("#{((input i) length)}" dataUsingEncoding:NSUTF8StringEncoding)))
(output closeFile)
Oh, incidentally, the #{} in the middle of the text string is a Nu convention that was borrowed from Ruby. Basically, it takes whatever Nu code lies between the curly braces (which can be anything), processes it, and then substitutes the output into the string. At the moment, the output is the length of the string in characters, but really it’s arbitrary code.
Now, that’s not especially beautiful, and it’s a bit hard to see why I care about using Nu instead of Objective-C for this task (unless I really like parentheses (which I (obviously) do, but that’s not the point)). It becomes more obvious when I decide that, really, the output method is ugly — the NSFileHandle class has only one output method, and it takes an object of type NSData. I can convert an NSString object to an NSData object using the dataUsingEncoding: message, but it’s ugly to have to do that every time. So, what I can do instead is this:
(class NSFileHandle
(- writeToString:(id)str is
(self writeData:(str dataUsingEncoding:NSUTF8StringEncoding))))
Now again, that doesn’t seem very special, until you realize something — NSFileHandle class is a base class in the Cocoa framework. It’s available in a library, but it isn’t available in source code. So, in my Nu script, I’m adding a new method to an existing class for which I don’t have the source code. Naturally you can also do this in Objective-C itself too, but with Nu it’s effortless. And, what’s even more interesting, this is an interpreted script. So I’m adding a new function to a library class in an interpreted script. What’s more, because code is data and data is code, my script can actually take input in the form of s-expressions and evaluate them, no matter what code they actually contain.
So, after some struggle, I’m beginning to see that this is the Nu way of doing things. Yes, the Objective-C libraries tend to be fairly low-level, but you can add utility functions to the classes to make them do what you want them to do. So, when writing a Nu script (and, right now, I’m using Nu primarily for writing scripts, generally little data processing scripts that take spectra (encoded as text files with wavelength and flux columns) and do useful things with them, like scaling them, redshifting them, whatever). If you run into something complex then, especially if you might be doing it in multiple places, turn it into a function (or a macro). My rule so far has been to build functions when what I want is to make a class do something it wasn’t designed to do (just add a new method to it), and macros otherwise, but there are likely lots of different ways to go about this.
So that’s what I’m doing right now, and it’s surprisingly fun. And once I’ve finished making my little utility scripts (rather, converting them from python), I’ll be able to use the exact same code to make myself really nice MacOS applications. Not to mention that it keeps me programming, and makes sure I keep my mind flexible in the particular way that coding demands.
Page last updated Sun March 23, 2008
All content on this page, including downloadable content, is © 2001-2008 by Brian York.