SBCL test failures on ARM

For hacking/prototyping/fun purposes I have a few embedded systems laying around. For example, I have a couple of Raspberry Pi systems, one of the original Raspberry Pi model B boards and one of the new Raspberry Pi 2 model B boards.

And on everything, I have the latest Steel Bank Common Lisp building.

On my Raspberry Pi, which is an armv6 device, I see the following failures in SBCL’s unit tests:

 Failure:            debug.impure.lisp / (TRACE ENCAPSULATE NIL)
 Failure:            debug.impure.lisp / (TRACE-RECURSIVE ENCAPSULATE NIL)
 Expected failure:   packages.impure.lisp / USE-PACKAGE-CONFLICT-SET
 Expected failure:   packages.impure.lisp / IMPORT-SINGLE-CONFLICT
 (62 tests skipped for this combination of platform and features)

On my Raspberry Pi 2, which is an armv7 device, I see the following additional failures:

 Failure:            float.pure.lisp / (SCALE-FLOAT-OVERFLOW BUG-372)
 Failure:            float.pure.lisp / (ADDITION-OVERFLOW BUG-372)
 Failure:            float.pure.lisp / (ADDITION-OVERFLOW BUG-372 TAKE-2)
 Failure:            debug.impure.lisp / (TRACE ENCAPSULATE NIL)
 Failure:            debug.impure.lisp / (TRACE-RECURSIVE ENCAPSULATE NIL)
 Expected failure:   packages.impure.lisp / USE-PACKAGE-CONFLICT-SET
 Expected failure:   packages.impure.lisp / IMPORT-SINGLE-CONFLICT
 (62 tests skipped for this combination of platform and features)

This says to me that, contrary to what some have told me, SBCL probably does need to distinguish the various ARM instruction set variants.

Is anyone actually working on SBCL on ARM?

I also have a DragonBoard 410c on the way, and it might be nice to have a fast Lisp on ARM64, though I suspect that’s a bit further out…

Arc in a nutshell: It’s no Dylan (and that’s too bad)

What’s the point of [Arc][1]? Infix-syntax [Dylan][2] is a much, much better language, especially once you add in the changes and features from the [Dylan Design Notes][3] and the infix version (but keep the prefix syntax). Really, Dylan is pretty much the Ultimate Lisp in a lot of ways.

Arc is essentially `(decr Scheme)` with a couple of interesting additions to try and make up for the downsides. Downsides like a lack of international character support (what decade is it again?!) and an unhygienic macro system.

[Dylan — as designed in the **early 1990s**][4] — really is `(incr Scheme)`. It’s essentially Scheme re-hosted atop an enhanced CLOS-like object system. With the prefix syntax, it’s even very Scheme-like in actual use.

So, yeah. If you’re interested in Arc, check out Dylan. It’s a better language, and there have been implementations available for 15+ years.

PS – The original Dylan had a [``][5] class. In the early 1990s.

[1]: http://www.arclanguage.org/
[2]: http://www.opendylan.org/
[3]: http://amigos.rdsathene.org/other/prefix-dylan/design-notes/home.html
[4]: http://amigos.rdsathene.org/other/prefix-dylan/book.annotated/preface.html
[5]: http://amigos.rdsathene.org/other/prefix-dylan/book.annotated/ch12.html#unicode-string-class0

It’s not the dynamic dispatch!

Joel has decided to blame the use of dynamic dispatch for Ruby’s speed issues:

Without knowing much about the implementation of Ruby, I would guess that the biggest issue is around late binding and especially duck typing, which prevents type inference or strong typing, which means that function calls will always be slow because you can never get something compiled down to the point where a function call is just a single CALL instruction (on x86)… you always have to be exploring the object, possibly even scanning a hash table to find the function you want to call.

In other words, “it’s always going to be slow because if it’s not strongly-typed it can’t be statically compiled to the most minimal possible instruction sequence!” Which is, simply put, a bullshit argument even if you ignore the fact that he said right up front it was bullshit.

There’s a lot that you can do to optimize dynamic dispatch. If you don’t believe me, take a look at the implementation of the Apple/NeXT Objective-C runtime, objc4. Go ahead, it’s Open Source. (The link is for the version that’s part of Mac OS X 10.4.7 for Intel processors.) It implements full Smalltalk-style dynamic dispatch — the same type of dynamic dispatch that Ruby uses. And what’s more, Ridiculous Fish also wrote a great article on how dynamic dispatch is implemented in the objc_msgSend() primitive — with particular attention focused on its performance characteristics!

No, it’s not message-based dynamic dispatch or “duck typing” (runtime polymorphism) that makes Ruby slow. It’s the fact that Ruby is a single-pass interpreted language. It’s not compiled to bytecode. It’s not compiled to native code. It’s scanned, parsed, and then immediately executed.

Imagine if your C compiler, or your Fortran compiler, or your Java compiler — or your Visual Basic compiler, for that matter — had to be invoked every time you ran your program. Imagine how slow that would be! That’s essentially what Ruby is doing, and that’s why it’s slow. Ruby 2.0 is planned to run on the YARV virtual machine, and there has also been work to compile Ruby code for LLVM. There’s nothing in Ruby’s nature that makes this a particularly difficult problem, especially since all of the issues of efficiently compiling dynamic languages with reflection and self-modification features were solved by Lisp in the 1960s and Smalltalk in the 1970s.

Incidentally, this is why I react so vehemently when people talk about “Lisp interpreters.” Lisp is almost never interpreted, specifically to avoid these types of performance issues. At the least most Lisp systems compile to a custom bytecode and then use an optimized bytecode engine to execute that. That way they can eliminate the scanning and parsing overhead — yes, it does exist for Lisp, because contrary to what Lispers may say, the language does have syntax — while still stay portable.

Others have also been piling on, such as Avi Bryant and Obie Fernandez. As Obie points out, Avi knows what he’s talking about. And so do folks who work with Objective-C intimately, day in and day out.

Programming language terminology lesson: Closures

In reading Beyond Java by Bruce Tate, I saw the following:

Java’s syntax lacks features like closures and code blocks (which let you pass a block of code as an argument).

Argh!

In the vast majority of languages that support them, a block is a closure! Blocks, closures, lambdas — they’re all just different words for the same thing! A closure is just a piece of code that carries around (“closes over”) definitions from the environment in it was defined, and can be executed later using those definitions, possibly taking some arguments as input as well.

The terminology distinction between blocks and closures probably comes from the days when Smalltalk blocks weren’t closures. That is, they would reference the environment in which they were executed rather than the environment in which they were defined. However, since at least the early 1990s, I believe all major Smalltalk environments have switched to representing blocks as closures.

Steve Yegge describes what’s wrong with Lisp

Steve Yegge, Lisp is Not an Acceptable Lisp:

You’ve all read about the Road to Lisp. I was on it for a little over a year. It’s a great road, very enlightening, blah blah blah, but what they fail to mention is that Lisp isn’t the at the end of it. Lisp is just the last semi-civilized outpost you hit before it turns into a dirt road, one that leads into the godawful swamp most of us spend our programming careers slugging around in. I guarantee you there isn’t one single Lisp programmer out there who uses exclusively Lisp. Instead we spend our time hacking around its inadequacies, often in other languages.

Steve does a very good job of articulating a lot of the things I dislike about Lisp, especially Common Lisp. One interesting thing, though, is that a lot (but not all) of the issues he raises are addressed by Dylan.

One of the more interesting things about Dylan in this context is that, despite not adopting a traditional message-based object system like Smalltalk or Objective-C (or their more static cousins C++ and Java), Dylan does push objects all the way down, but in a functional style. It appears to work pretty well, making it easy to define both nouns and verbs in the combinations a developer might need, and even (through its hygienic macro system) allow developers to extend language syntax too.