Anyway, a continuation is essentially a closure that, in addition to closing over the lexical environment, also closes over the control chain. (Well, OK, control stack, but if you’re doing continuations odds are it’s a singly linked list rather than a real stack.) CS texts generally go on about continuations being “the rest of the program” or “gotos with arguments” or suchlike stuff. If those float your boat, great—they never made sense to me.

Yeah, I think it depends on whether you are looking at this from the angle of implementation or theory. If you’re writing a VM, then you think in terms of closing over the control chain. If you’re doing denotational semantics, you think in terms of lambdas for the rest of the program.

So I rewrote this thing yet again. I didn’t use any of Omni or Camino’s code, although having seen their implementations did make mine go pretty quickly. And now I’m relatively happy, since my table-like view works, and the licensing works out the way I wanted. But still, it seems like there’s something wrong that there’s all that source code out there that does exactly what I want, and that I can even download and look at, but cannot use. Were I a more philosophical or political person, I might even have something Important to say about it.

IMO, this kind of view should really be part of Cocoa to begin with, as it is in Java.

So Eric Raymond says that meta data or, as he puts it, file attributes, are important. Just as Mac OS X drops support for such meta data. So the Linux community learns this from Mac OS X, but where did OS X learn no meta data from?

Erik Barzeski posted about iterators in Cocoa, so I thought I’d give some perspectives from other languages. I think there are really two concepts here: iteration and generation.

I don’t know that everyone agrees with these definitions, but to my mind iteration is about obtaining a sequence of values, without caring about how those values are produced. This is embodied by the NSEnumerator interface, java.util.Iterator, and the Python iteration protocols. Iteration is about how you get the values that you want to consume.

In the above example, Python will call objectStructure’s __iter__() method to get an iterator object.

Generation is about how to produce the values. The generator returned by -[NSArray objectEnumerator] probably keeps a reference to the array and remembers an index into that array. When you send it -nextObject, it increments its counter and returns another object. java.util.Iterator is similar. This is straightforward to implement for list-like things. For instance, my SQLite wrapper includes an NSEnumerator subclass for rows in a database table. It took seconds to write. But how do you write this kind of generator for the nodes in a tree? Or the interesting tokens in a mail message? You need to remember more state than just an index, and it can be a real pain. In practice, people often perform a full traversal of the structure, stuffing the objects into an array, and then return the array’s generator. That makes the code much simpler, but inefficient.

I’ve seen two other ways of writing generators, which work better in the more complex cases. What I call the closure approach inverts the problem. Instead of writing code that gets values from a generator object and then does something with them, you put your code in a closure (a.k.a. lambda or block) and give the closure to the generator. This is the approach taken by Smalltalk and Ruby, and it could also work in other languages with closures, such as Lisp and Perl. From the caller’s perspective, we get something like this (in Ruby):

objectStructure.each { |o|
# do something with o
}

Here, the block (in curly braces) becomes an argument to the method call. The each method traverses objectStructure and evaluates the block many times, passing in different o’s.

Other languages use what I call the yield approach, which was popularized by CLU in the mid-70s. Under this approach, generation is handled by a function that can, in effect, return multiple times. Instead of using a return statement to return, it uses a yield statement. yield is like return, except that the next time the function is called, it resumes after the last-executed yield statement.

Interestingly, the keyword that Ruby uses to evaluate a block parameter is also called yield. It’s used for roughly the same reasons, but what’s going on under the hood is quite different. Ruby’s yield is like a function call, whereas CLU/Python’s is like a function return.

I like return-style yield better. It can even be used to create infinite generators (a.k.a. streams):

def odds():
i = 1
while True:
yield i
i = i + 2

Unfortunately, there is no yield, of either kind, in the C family. You can kind of fake it using macros.

bbhexdiff is a Perl script that uses the command-line hexdump tool and BBEdit’s Find Differences command to compare hex dumps of files. As the name suggests, it’s somewhat based on John Gruber’s bbdiff command.

Create a new, empty project. Set it up as you like it, so it’s easy for you to use. Include your favorite libraries, and turn off the optimizers (which slow down compilation and make low-level debugging more difficult). Now leave it, empty, sitting there. This is your teststand.

Recently in this space I complained that XML is too hard for programmers. That article got Slashdotted and was subsequently read by over thirty thousand people; I got a lot of feedback, quite a bit of it intelligent and thought-provoking. This note will argue that XML doesn't suck, and discuss some of the issues around the difficulties encountered by programmers.

Parrot architect Dan Sugalski explains why the two big VMs are poorly suited for dynamic languages. He then demystifies closures without mentioning Lisp and promises a similar treatise on continuations (which the JScheme folks also decided not to support on the JVM).

Operations in Lisp, Scheme, and other dynamically-typed languages typically dispatch on representational type information rather than intentional type information. Several broad classes of bugs and confusions can be traced to improper attempts to recover intentional type information from representation types.

In the early history of continuations, basic concepts were independently discovered an extraordinary number of times. This was due less to poor communication among computer scientists than to the rich variety of settings in which continuations were found useful.

MagicHat reconstructs @interfaces from Objective-C frameworks and attempts to find the corresponding header files and documentation. Unlike class-dump, it provides a real human interface, although it’s more difficult to use MagicHat on arbitrary files.

Most work on computational complexity is concerned with time. However this course will try to show that program-size complexity, which measures algorithmic information, is of much greater philosophical significance. I’ll discuss how one can use this complexity measure to study what can and cannot be achieved by formal axiomatic mathematical theories. In particular, I’ll show (a) that there are natural information-theoretic constraints on formal axiomatic theories, and that program-size complexity provides an alternative path to incompleteness from the one originally used by Kurt Gödel. Furthermore, I’ll show (b) that in pure mathematics there are mathematical facts that are true for no reason, that are true by accident. These have to do with determining the successive binary digits of the precise numerical value of the halting probability W for a “self-delimiting” universal Turing machine. I believe that these meta-theorems (a,b) showing (a) that the complexity of axiomatic theories can be characterized information-theoretically and (b) that God plays dice in pure mathematics, both strongly suggest a quasi-empirical view of mathematics. I.e., math is different from physics, but perhaps not as different as people usually think. I’ll also discuss the convergence of theoretical computer science with theoretical physics, Leibniz’s ideas on complexity, Stephen Wolfram’s book A New Kind of Science, and how to attempt to use information theory to define what a living being is.

The MulleEOInterface framework is a binary replacement for the EOInterface framework that Apple delivered in their Objective-C version of WebObjects (4.5). It's the link between EOControl and AppKit. With EOInterface you could conceivably - if you had a IB palette - easily create fairly complex desktop applications using Interface Builder and no code at all!

We have been teaching our customers to regard their data as a precious resource that should be milked and reused by finding many possible ways of summarising, viewing and updating it. However, we programmers have not yet learned to treat our source code as a similar structured data resource.

Object-oriented programming gains much of its versatility through polymorphism: objects of different kinds can behave in similar ways, given the right contexts. But most OOP programming is single dispatch; that is, just one designated object determines which code path is taken. Conceptually, a more general technique is to allow all the arguments to a function/method to determine its specialization. This article presents an implementation of multiple dispatch in Python, and shows examples where this makes for better programs.

Good thing my Mac can boot into OS 9. DiskWarrior 3, which is OS X–native, isn’t out yet, and last week I had to use DiskWarrior 2 to fix my internal drive before the Mac would even boot. So much for a stable operating system protecting against catalog damage. DiskWarrior is great, but with all the files Mac OS X installs it takes hours and hours to run. I wonder what Alsoft plans for PlusOptimizer.

PyTextile is a Python port of Textile, Dean Allen’s Humane Web Text Generator. It supports all the features of the original, with the exception of converting high-bit characters to their HTML numeric entity equivalent, because that’s some bad-ass PHP goin’ on and I don’t pretend to understand it.

David Hardy says that the film that just won an Oscar® for Best Documentary isn’t a documentary. In fact, Hardy goes so far as to call it “deliberately, seriously, and consistently deceptive.” And provides evidence.

Safari does a great job at rendering. It’s approximately as compatible with interactive sites as iCab. (Some work in one but not the other, and in both cases I occasionally have to use Internet Explorer.) I have some quibbles about the way it handles downloads and such, but it’s still beta and I think this stuff will all improve.

The area I’m concerned about is font rasterization. I don’t like fuzzy text, and Safari uses CoreGraphics, which is incapable of drawing nice crisp text. Some will say this is a feature, that the poor spacing is because it is more precisely following the font metrics. That’s taking WYSIWYG too far. The first job of a browsing application like Safari should be to make the content readable. If that means using a hand-tuned bitmap that is less true to the actual printed font, I’m all for it.

I am also well aware that many people like small anti-aliased text. Fine. I don’t want to take it away from you, and Apple wouldn’t listen to me anyway. However, I think Apple should let the user control the tradeoff between flavor and readability. This should be a system-level preference, and it should also be overridable at the application or font level.

Until Apple fixes this or the iCab folks improve their CSS support, I will be switching back and forth between iCab and Safari depending on the length and type of content, and on how much the page I’m reading uses CSS. (Developers: I would pay good money for a standards-compliant browser that uses QuickDraw.)

Here are some examples of how iCab and Safari render the documentation for NSMutableArray.

This is the class description in iCab. The body text is Geneva 10, the header is Helvetica, and the code is in ProFont. The text is crisp. It may not be beautiful, but I find it very easy to read. Note the way the descenders are drawn in the underlined text and how easy it is to see ProFont’s exaggerated punctuation.

This is the class description in Safari. The fonts are Geneva and ProFont. (Safari doesn’t provide an option for finer control, except through a custom stylesheet.) The bold text doesn’t appear bold because CoreGraphics doesn’t create synthetic styles. The descenders and the underlining are mashed together. The “anObject” in the code font stands out, jarringly so. The punctuation in the extended code example is muddy.

This is the top of the page in iCab. The header is anti-aliased with QuickDraw, and I think it looks nice. The indented headers appear very bold. My only complaint is that there’s a bit too much spacing after the opening parens.

Here it is in Safari. Now it’s really obvious that Safari can’t do bold Geneva. The paren spacing is much better, though.

Here’s the same page using Safari’s default font, Lucida Grande. Now the bolds look nice. I’ll use Lucida Grande from now on, because it’s the font Apple uses to showcase CoreGraphics.

In Safari, you can’t even tell that the apostrophes are smart. The en-dash after the “C” looks shorter than the hyphen, and it’s really fuzzy. One thing I like about Safari’s rendering is that it doesn’t underline the space after “Python”; iCab does this, even though there’s a line break.

The SoftwareToGo Product Preview Station (PPS) stores descriptions and demos of each product it carries. If you want to buy something, the PPS prints a bar-coded ticket that you take to the counter, where a CompUSA uses the Order Fulfillment Station (OFS) to burn a CD, produce customized DVD-style casing, and individualized registration information. Basically, it’s like some mad scientist mixed a product finder application with the large item tags at appliance stores and a service like eSellerate and dropped it in CompUSA.

This is the guide that I wish I had when I first started out. It would have helped me to avoid certain situations. I’ve started a few friends in on blogging lately as well, and so this article could have served them too. Perhaps it’ll help others.

I really like the Objective-C messaging syntax, especially when combined with Apple’s naming conventions. When you have an NSMutableArray, there is absolutely no ambiguity between -addObject: and -addObjectsFromArray:. In Python, I still confuse append() and extend(), perhaps because in Lisp append is for appending the elements of a list, whereas in Python it’s for appending an object.

All programmers are optimists. Perhaps this modern sorcery especially attracts those who believe in happy endings and fairly godmothers. Perhaps the hundreds of nitty frustrations drive away all but those who habitually focus on the end goal. Perhaps it is merely that computers are young, programmers are younger, and the young are always optimists. But however the selection press works, the result is indisputable: This time it will surely run, or I just found the last bug. —Frederick P. Brooks, The Mythical Man-Month

Mac OS X Hints has a tip for a LaunchBar AppleScript that lets you type in a search term for your favorite engine. It’s a nice idea, but Huevos supports multiple engines and launches faster than an AppleScript applet.

These slides from a Perl talk include a good little introduction to ML- and Haskell-style type checking:

If we put a list of strings into our sort function, the
compiler says that when it returns, it will have turned it into a list
of ints. This is impossible. One possible explanation is
that the sort function never returns. And in fact this is
the case. The sort function, as we wrote it, goes into an
infinite loop on any input except the empty list. This means that the type checker has found an infinite loop bug in our program. Ponder that for a minute.

tankknight’s review on VersionTracker recalls the words of Steven Frank and John Gruber. This guy never asked for help, and didn’t provide any contact information. Since the review isn’t offensive or blatantly false, VersionTracker will probably just leave it there.

The key point about this figure is that the rate of innovation in Linux is greater than the rate of increase of the lower limit of user expectations. Therefore it is inevitable that the Linux curve and the lower limit of user expectations curve intersect.

Dave Hyatt responds to John Gruber, who said that Safari shouldn’t anti-alias Geneva and Monaco. Hyatt rightly states that anti-aliasing is ultimately subjective. This is why Mac OS X should provide a way to turn it off—and render and space bitmapped fonts properly, so they don’t look like this.

This is the Apocalypse on Subroutines. In Perl culture the term
“subroutine” conveys the general notion of calling something that
returns control automatically when it’s done. This “something” that
you’re calling may go by a more specialized name such as “procedure”,
“function”, “closure”, or “method”. In Perl 5, all such subroutines
were declared using the keyword sub regardless of their specialty.
For readability, Perl 6 will use alternate keywords to declare special
subroutines, but they’re still essentially the same thing underneath.
Insofar as they all behave similarly, this Apocalypse will have
something to say about them.

Wow, there’s some good stuff in there—better static checking, multimethods, macros, slurping parameters, keywordless lambdas—but at what expense in complexity?

In an ominous warning for his son, Mr Bush Sr said that he would have been able to achieve nothing if he had jeopardised future relations by ignoring the UN. “The Madrid conference would never have happened if the international coalition that fought together in Desert Storm had exceeded the UN mandate and gone on its own into Baghdad after Saddam and his forces.”

On the one hand, I have a lot more confidence in the elder Bush’s judgement; on the other, we wouldn’t be discussing this now if he had finished the job in ’91.

As someone who almost became one of those military officers, I must take exception with Lee’s “smarter-than-the-average-automaton” crack. Despite how they may be portrayed from the Hollywonk perspective, by and large your average military officer is a highly dedicated, smarter-than-the-average-citizen…

I can’t comment on the “average” military officer, however all the military people I’ve met professionally have been extremely smart. What a relief that was to discover.

Dean Esmay wrote an article about why it was a good idea for the Bush administration to go to the U.N. before proceeding against Saddam. I don’t know any people so hawkish to think that was a bad idea. Personally, I think Bush made up his mind long ago. He went ahead with the U.N. dance because, once you rule out immediate action, it’s a win from all angles. It gives time to build domestic and international support while deploying the forces. It provides the possibility that the U.S.’s action will be with U.N. approval. Most importantly, it furthers the administration’s long-term goals. They want the U.N. to be effective, or to clearly demonstrate that it is not. They probably expect the latter and are eager to increase their justification for ignoring it, both in post-war Iraq and in whatever’s next on their agenda.

Looking at it from the point of view of many years of striving to be logical so that what I type into my computer actually makes sense, I don’t know any other way to describe the [NYT] op-ed statement but with one word: stupid.

I tend to like using lots of separate windows. iCab introduced the idea of letting the user choose to open new windows in the background, and that has served me well. It has a command for stacking them, and in Jaguar all OS X apps can cycle through windows with Command-`. I haven’t liked the tab implementations I’ve seen because you can’t fit very many tabs in the window width before the titles become as unreadable as the Windows Taskbar (or there are awkward scrolling tabs like in older Metrowerks programs). This is worse for me because I tend to use narrow windows. The vertical mock-ups are interesting, but I agree with Dave Hyatt that thumbnails aren’t the answer. Chris says that he doesn’t like the vertical layout because it takes too much screen space. Well, I don’t see how you’d do it with less and still be able to read all the titles. I certainly don’t think a drawer is the answer. It would be better to use a design like Entourage’s folder list. That is easy to hide and show, and it fits in well with the keyboard loop. But perhaps Hyatt and crew can think of something better.

Opens Terminal windows for the items selected in the Finder (or the items dropped onto the droplet). If a folder or package is selected, the Terminal window’s working directory will be that folder. If a file is selected, the working directory will be the file’s containing folder.

Creates a window in Mailsmith to reply to the current Mail.app message. (I use Mail.app for my mailing list mail, since it handles large volumes of mail better than Mailsmith. However, Mail.app’s mail composition interface is terrible, so I wrote this script to let me do my replies in Mailsmith.)

When my brother tries to play the DVD that he just burned, the audio starts two seconds after the video, and they remain out of sync for the rest of the DVD. This problem did not occur in iMovie or in iDVD’s preview. Does anyone know how to fix this without burning through lots of disks experimenting?

“Manager” has come to be a danger signal to me—warning of lack of thought on behalf of the application’s designer. It either means (a) that the designer couldn’t be bothered thinking of a truly descriptive name, and begs the question, “What else couldn’t the designer be bothered with?”, or (b) that the designer hadn’t carefully thought through the role and responsibilities of this class.

We’re being told here that break-even is perhaps a third of the volume of a gold record.

Now, how do you make money in such a business? By maximizing the win. You aren’t really after gold records, you want platinums, multi-platinums, and bankable artists that can do it every two years, to make up for the 90% of losers and yield a profit.

In Python (and other languages), classes are themselves objects that can be passed around and introspected. Since objects, as stated, are produced using classes as templates, what acts as a template for producing classes? The answer, of course, is metaclasses.

Eric Blair’s blog has gone live. I think I first met Eric at Macworld Boston some years ago. He’s been reviewing for ATPM for quite some time now and has beta tested most of my software. So I guess you could say that I value his opinion. :-)

John Gruber weighs in on the discussion that I previously mentioned. I see where Rentzsch and Gruber are coming from, but I’m not convinced. I’d be happier with a well-worded dialog that made cancelling the default option.

If you invoke Undo, the Finder will move the replacement item back to its previous location, but it will not bring back the item that was deleted.

If there is a bug, it is this. The Finder should not enable its Undo command if it cannot provide a complete undo. Imagine if the replaced item is not in view. After choosing Undo, the user will think that it has been restored. In fact, even if the containing folder is in view, the user may simply trust that since the Mac didn’t complain the Undo completed successfully.

I believe there is a solution which should make everyone, Rentzsch and Bumgarner alike, very happy: the Finder should move the replaced items to the Trash.

Sounds like a good idea. It brings back happy memories of Central Point’s TrashBack. Of course, the Finder engineers would still have to make a choice in the case where there isn’t enough disk space.

With my suggestion that replaced items be moved to the Trash instead of deleted, this poses a problem. Aliases pointing to the original item will resolve to point to the original item in the Trash, not the replacement in the original location. If you empty the Trash first, there won’t be a problem, but the whole point of the Trash is that you’re allowed to keep items sitting inside it. I think this might be solvable by adding some smarts to the Alias Manager, such that if an alias’s target is in the Trash and there is a newer item in the original location, it could reassign the alias to the new item.

I’m not an expert on this stuff, but it appears that the Finder could exchange the file references so that aliases point to the new item, not the one in the trash. No need for an “if it’s in the trash” hack.

All this said, I’m not sure I’d like the Undo command to bring the original item out of the trash, because I doubt the Finder can guarantee that the restored item will be identical to the original. Another program could alter it while it was in the trash. This is similar to the problem where the Finder’s Copy command copies a reference to an item, not the item itself, thus breaking the clipboard’s standard behavior. Let the user restore the item manually, if desired, but don’t call it Undo.

There is no difference between “Compiled Script” and “compiled script”. The idea that one does resource-fork and one does data-fork is a myth.

I must admit to believing in this myth, but testing with Script Editor and Super Get Info confirms what he says. The best way to make resource-fork compiled scripts is with Script Debugger, though according to Nebel you should also be able to duplicate and then edit an existing resource-fork script. Why not just use a data-fork script? Because some applications don’t yet support them.

Making a linguistic theory is like specifying a programming language: one typically devises a type system to characterize what utterances are acceptable, and a denotational semantics to explain which statements entail which other ones. Along this connection, programming language research can inform linguistic theory and vice versa; in particular, computational side effects are intimately related to referential opacity in natural languages. In this talk, I will illustrate this link by using continuations and composable contexts to analyze quantification (as in “every student passed”).

The Scope framework seems to extend Swing with ValueModel-like features, thus reducing the need to write glue code to connect model and view objects. This is one Cocoa’s weak areas, but Apple apparently had a solution in EOF, which is now available only as part of WebObjects. (Link via Jonathan Rentzsch.)

Microkernel operating systems should expose continuations, not threads, as the low-level interface to the kernel. Threads should be provided as a library in user-space layered on top of the microkernel. Richard Draves’ thesis demonstrated that using continuations as a programming technique within the MACH 3.0 kernel simplified the code and vastly improved performance.