Talking with Mikel Evins about the Lisp-based Newton OS.

This text was originally published in 2004.

It is little known that an early version of the Newton OS from Apple was written mainly in Lisp. Apple created a Lisp-like language called Ralph. The operating system was called Bauhaus and the development environment was a hacked up version of Macintosh Common Lisp called Leibniz.

The shipped version of the Newton OS was very different. Mikel Evins, who worked in the Newton group at Apple, answered a few questions (2004) about the technology on the Yahoo Lisp machine forum. I've edited them a bit and put them online. It all sounds very exciting...

Bauhaus: Newton OS written in Ralph.

Ralph: a Scheme+CLOS variant, later known as Dylan.

Leibniz: Development environment, MCL plus a Ralph compiler that cross-compiled to the ARM, plus a remote listener.

MCL: Macintosh Common Lisp.

Q: Mikel, I have some questions on the Bauhaus topic. When did the development on Bauhaus happen?

Mikel: Newton development started probably 1989 or so. The Bauhaus project and the Junior project (which became the shipping product) both started some time in late 1992. I worked on Bauhaus until it was cancelled in early 1994.

Q: What would be a typical usage szenario of the machine? It was not a small PDA like the released Newton, right?

Mikel: We assumed that people would want a slate-like device in a variety of uses, from personal uses for note-taking and use of a computer that was more convenient than a laptop (laptops were bigger then), and also for a large variety of more specialized uses--for architects, inventory-control specialists, health-care professionals, etc. etc.

Q: What kind of applications would have been written for it? Were there any demo applications that were written to show the potential?

Mikel: Yes, but they were fairly thin. Remember that it was only six of us (really five, because Larry spent most of his time being an executive--though I did debug code that he wrote for Bauhaus :-)). and we were writing a whole OS (above the kernel).

Mikel: We had an address book, a note-taking application, various drawing tools, a frame-based general database application (that I called the "encyclopedia", a help system, scheduling tools, and other things I don't remember. Matthew, who did our windowing and graphics system, did a bunch of small graphic demos with very slick animations, smooth scrolling, and all sorts of stuff. When it started to look like we were going to be cancelled, he went into overdrive producing code that he hoped would convince management to let us try to build a TV box of some kind on the platform.

Q: How much code was it in the OS?

Mikel: Excluding the kernel, between 50,000 and 100,000 lines of code. The leverage was high--we had a user experience that felt fairly rich and complete in that amount of code.

Q: How many developers have been using the Lisp/Ralph OS?

Mikel: Six: Larry Tesler, Yuying Chow, Ken Dickey, Matthew Maclaurin, Jim Grandy, and me. Plus around a dozen people from other parts of the team when testing it and participating in demos.

Q: So, Bauhaus was written in Dylan?

Mikel: When I was working on Bauhaus (and before, on the first iteration of Newton OS) Dylan was even more a Lisp than it is now. It was called "Ralph", and was basically Scheme+CLOS+a couple of ideas from other functional languages+a few things to please Smalltalk hackers at Apple. The development environment was a hacked version of MCL that supported two compilers and runtimes: (1) the Common Lisp Compiler and runtime, which ran on 68K hardware and targeted 68K hardware; and (2) the Ralph compiler and runtime, which ran on 68K hardware, but targeted ARM hardware (first on ribbon-cabled Newton prototype boards, and later on development prototypes of actual Newton hardware connected by means of Nubus inserts). There were lengthy meetings with the Apple Cambridge team that was designing Ralph and various interested fractions at Apple, arguing for their favorite language features. The strongest lobbyists were Lisp and Smalltalk programmers.

Q: What would have been the main differences of Bauhaus to the released Newton OS?

Mikel: Everything above the kernel was written in Dylan, except for 7 very low-level QuickDraw routines. Size in RAM was about twice the size of the C++ version. The UI was a littler richer and a little faster, and built in Dylan using a graphic system made by wrapping those 7 QuickDraw primitives in Dylan and building a graphical language on it.

Mikel: It supported mobile software agents (but there was debate about how this could be made both robust and safe).

Mikel: It had a means of automatically generated UI elements from READ-like forms with class specifications for the arguments; for example, there was a macro get-input-from-user that was like a binding form (like LET*) with class annotations; it dynamically constructed the UI to get the values for the bindings. It had nestable stylesheets for describing the appearance of UI elements (sort of like CSS for UI, but back when the Web was brand new and the W3C What's New page still listed all the websites in the world :-)).

Miekl: It had a novel event-handling system capable of supporting arbitrary user-defined events. The event system identified events by pattern-matching.

Mikel: It had a frame system used to implement a knowledge base that stored things like prototypical Person and Place and Date objects, and supported fuzzy comparisons. The so-called "IA" ("Intelligent Assistant") subsytem used these frames so that it could guess things like the fact that when you write "Joe" you probably mean "Joseph Smith" or "Josephine Baker" from your address book. It was also used for the help system, so that it could guess that, for example, a sequence of actions was probably intended to establish a machine-to-machine connection and pop up information to help you do that, and for the event-handling system so that you could declaratively define new classes of high-level events and handlers for them.

Q: Sounds a little like MacFrames married with the Newton's soups.

Mikel: That's no accident! I and the main graphics/windowing guy worked together before on a knowledge-based automated testing system used to qualify System 7 for release; that system was written in MacFrames. Before that, I wrote a UI modeling system called Panels on MacFrames.

Mikel: The frame system I wrote for Bauhaus also supported relatively elaborate facets and annotations.

Q: What kind of high-level events would that be? Could the user define those?

Mikel: Yes. The idea was that you could plug a sequence of lower-level events together and use a property sheet to perhaps parameterize them, thus creating a novel kind of event. Sort of like constructing AppleScripts by recording UI actions, but in smaller, easier to understand and easier to debug pieces. (One of the things I wrote for the automated testing system was an application that watched what the user did and constructed a representation of the observed actions that could be replayed on another system; it represented actions not in terms of low-level MacOS events, but in terms of abstract state transitions described in terms of frames that represented application features, so that moving to a different machine with different screen layout and so forth would not break the playback. Some of the ideas for the event system came from combining that experience with the experience of Jim Grandy, who actually wrote the event system, and who had earlier worked on Garnet.)

Q: Was the event propagation like in the released Newton OS, where the event propagation was on some 'contained in' hierarchy and on the prototype hierarchy (IIRC)?

Mikel: If I remember right, events propagated up a containment hierarchy of visual objects, and were pattern-matched against 'subscriptions' at each layer. (That is, an agent could 'subscribe' to an event pattern and would get a chance to handle any event that matched it as it bubbled up through the containment hierarchy.) The Dylan runtime did not use a prototype hierarchy in the same way as the shipping version; we used generic functions for most of the things they used is-a relations for.

Q: Did the IA also support these commands like in the released version with some support for phrases like (from memory): 'add meeting with mike' and then provided some prefilled dialogs? A bit of this reminded me of the CLIM command language, but with some 'richer' syntax.

Mikel: Yes, we supported this. Yu-ying Chow used my frame system to implement more extensive natural-language stuff (and "concept" stuff) than the shipping version. We wanted higher-level data types for the user - Person and Date and Place and Activity, defined as frames with a relatively rich pseudo-natural language API and UI.

Q: Did it use color?

Mikel: Yes, in the sense of early NeXT machines. :-)

Q: Was the constructed GUI screen resolution independent?

Mikel: No, though it was adaptive to different screen resolutions. I thought it should have been more vector-based, but the fellow doing the graphics, Matthew MacLaurin, was a very pixel-oriented guy at the time.

Q: Was the GUI multi-threaded?

Mikel: No. It would have been eventually; Ken Dickey was hired to implement the threading system, but we got cancelled before that project bore fruit.

Q: Was there any use of the mobile agents?

Mikel: Only internally, for experimentation.

Q: How different is the development environment from the NewtonScript IDE?

Mikel: Totally different in every way. It was an application called "Leibniz", which was basically MCL plus a Ralph (Dylan) compiler that cross-compiled to the ARM, plus a remote listener for interaction with the ARM-Ralph runtime and other tools (e.g. inspectors, steppers, etc.). It was basically MCL, but with Dylan as well as Common Lisp.

Q: Was there some code organization like in the later Dylan Technical Preview? With browsers, where you edit code in-place and the code was more retrieved from a database than edited in files?

Mikel: No, nothing like that. It was really just MCL (though we did have good xref tools). At the time, there was much frustration that Apple Cambridge spent so much time on their new development environment, and not as much as we wanted on making improvements to the Dylan runtime (for example, we hired Ken because we concluded that Cambridge would not get around to threads in time to matter to us). That said, I have nothing but respect for what Apple Cambridge accomplished.

Q: Was the User Interface similar to the one shipped with the released Newton?

Mikel: In some ways, yes, in some ways no. The shipped UI was one of three developed. The original UI was written in Dylan, and had some interesting features (for example, pervasive use of non-rectangular windows), but it was criticized for being slow and for being too much like conventional desktop windowing systems. The engineering group underwent a reset in which 85% went off to rework Newton based on the C++/NewtonScript environment championed by Steve Capps and Andy Stadler, and a few of us were asked to see if we could do a better Dylan-based environment. You've seen the shipped UI. We intentionally tried to make our look like that, but with some additional capabilities, notably more animation and style-able elements based on nested stylesheets.

Q: Did the UIMS use generic methods / classes? Or was it prototype-based like the one of the released Newton?

Mikel: It used generic functions and classes, but also many singletons for UI customization, and it used the frame system for reasoning about what to display.

Q: Was there a User Interface designer?

Mikel: No. The UI implementor instead spent his time writing a declarative specification language for UI, which was intended to be easy enough to use that you wouldn't need a UI designer. You would control what elements appeared using type annotations, and would control how they looked using the stylesheets. The idea sort of foreshadowed DHTML and CSS and XUL.

Q: How did you make sure that the declarative specification language was predictable and delivers enough diagnostic messages for problems/violations/...?

Mikel: We didn't. It would have been a problem. We would have required interactive graphical tools.

Q: What did an application look like? Physical and from a user perspective?

Mikel: This is an interesting question, because there was some debate about exactly what an application was. In practice, it was usually some frames, plus some UI specifications, plus some style information, plus maybe a few methods and classes. We spent a bunch of time trying to decide how to tell whether it was okay to install something, because we had made it so easy to migrate code from one system to another and to dynamically update the system.

Mikel: User-wise, an application usually consisted of one or more new icons in one of the lists of tasks you could accomplish, plus maybe a new kind of "paper" that had either new recognizers or new things you could do with the old recognizers, plus some new pages and prompts in the IA and help, plus maybe some new kinds of objects you could store and search in your frame repository.

Mikel: We were trying to make it possible to make applications simply by plugging pre-existing objects together dynamically.

Q: How was the application organized? Was there some application description like a DEFSYSTEM? Was it graphical?

Mikel: In fact, we used a hacked version of mk:defsystem.

Q: Was it possible to develop on the machine?

Mikel: No; you needed a Mac running Leibniz. Your Dylan listener ran a REPL on the Newton, but you needed the Mac to talk to it and to compile Dylan code.

Q: Wasn't there any need for an interpreter or compiler on the machine?

Mikel: We thought so; we didn't get around to it before we were cancelled. There were many ideas that did not get worked out in practice.

Q: Was there ever anything written about Bauhaus or is everything in your head?

Mikel: Plenty was written, both documentation and code. A couple of years ago, in response to queries from someone else, I tried to get Apple to give me permission to redistribute both, but they're not interested. Nowadays I think whatever you can get is in the realm of ideas for discussion.

Q: *Why exactly* did Dylan go to an infix syntax? Whose idea was it?

Mikel: That's hard to say. One of the most-commonly-heard complaints in the early language-design meetings was that the new language was a Lisp. (Naturally, this complaint came only from participants who were not Lisp programmers. Actually, it didn't come from Smalltalk programmers either; they mostly complained that they really wanted the names of functions to be self-documenting in the sense that Smalltalk method selectors are, and they seemed to be satisfied on that point by keyword arguments; and they complained that they wanted stronger encapsulation of private data than typical Lisps give you, and they seemed to be satisfied on that point by the module system).

Mikel: There were repeated and heated arguments about language syntax, with most of the heat coming from non-Lisp, non-Smalltalk folks, who felt strongly that there should be an infix syntax. The implementors, all of whom were Lisp people (one of them was Moon!), seemed pretty much not to care one way or another about syntax, or at least ot have no very strong feelings about it. I was solidly in the Lisp camp, but I actually favored the invention of an infix syntax; I saw it as a harmless addition to make the language more attractive to non-Lispers.

Mikel: I believe now that I was wrong: the infix syntax did not cause Dylan to succeed, and I find it distinctly inferior in practice to the s-expression syntax that I used for several years. As a matter of fact, my favorite programming language of all time is not Common Lisp, but the S-expression-based Dylan (later Dylan versions don't excite me). High on the list of things I would like to see is a new implementation of something very close to that language, with several things designed to bring it forward to today, notably libraries supporting POSIX, multithreaded programming, Internet protocols and data formats, and good XML support. DUIM would be nice, too.

Q: Did Ralph make use of Lisp-like macros?

Mikel: Yes, though they were defined in Common Lisp, rather than in Dylan.

Q: Dylan vs. Guile (a Scheme).

Mikel: Things the old Dylan had that I would miss in Guile:

absolutely everything is an object in the sense of its object system

native code compiler

iteration protocol (and the generally well-thought-out collection classes)

comparison protocol

a single convenient form for binding single or multiple values

singletons (yes, I know it's possible to implement them using the MOP)

functional features like curry, rcurry, compose, complement, disjoin, and so on

sealing

the condition system

the module system (I prefer it to that of Guile)

grew fond of several Dylan conventions that differ from Scheme (e.g. the use of "bind" in place of "let")

Mikel: On the other hand, Guile does provide some things I would misss if I had to go back to the old Dylan, notably threads and SRFI support. As I've said above, I'd also like to see a modern Dylan support POSIX and XML and Internet standard protocols and data formats.

Q: Was there some memory protection for Dylan apps?

Mikel: Honestly, I don't remember. The microkernel supported such protection; I don't remember whether the Dylan runtime used its fcailities or ran everything out of a single heap.

Q: On the relationship between software and hardware groups.

Mikel: When we were working on the various flavors of NewtonOS, the software and hardware groups were not separate. I mean, of course, there were hardware engineers and software engineers, but the overall group was relatively small and everyone worked pretty closely and met together regularly and so on. It is liberating, not only to throw away assumptions about the OS and re-envision it in more congenial terms (as you said, as a live system, not an undead thing), but also to throw away the assumption that the system is constrained by the hardware that is given off-the-shelf. If you have the sense that it is possible to redesign the hardware, then you can begin to think about what you would like the hardware to be able to do. For example, we decided it would be good if you could carry your Newton around with you and just automatically be on a network whenever you were close enough to a network node. This is commonplace today, but it was blue-sky in 1992. We had software and hardware both, though, so we could think that way. The hardware engineers had Macintosh SEs on carts with their guts hanging out and ribbon-cabled to transceivers, testing spread-spectrum comm hardware and associated networking stacks. Those early proto-Newton systems would notice when they got close enough to a repeater to negotiate the appropriate handshakes and automatically put themselves on the net. Crazy in terms of what was available off-the-shelf in 1992, but not at all unreasonable if you are willing to think about new hardware as well as new software.

End of story.