Arc in a nutshell: It's no Dylan (and that's too bad)
[info]chanson
What's the point of Arc? Infix-syntax Dylan is a much, much better language, especially once you add in the changes and features from the Dylan Design Notes 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 — really is (incr Scheme). It's essentially Scheme re-hosted atop an enhanced CLOS-like object system. With the infix 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 <unicode-string> class. In the early 1990s.

SBCL 1.0
[info]chanson
Steel Bank Common Lisp 1.0 was released yesterday! Download a binary if you want a decent, fast Common Lisp for Mac OS X or a variety of other platforms.

Or if you're feeling adventurous — and have a Common Lisp installed already, for bootstrapping — you can build SBCL yourself from source.

Hopefully someone will create a useful Cocoa bridge soon…

It's not the dynamic dispatch!
[info]chanson
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
[info]chanson
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
[info]chanson
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.

Dylan and Lisp macros
[info]chanson

Jonathan Bachrach & Keith Playford, D-Expressions: Lisp Power, Dylan Style (1999):

This paper aims to demonstrate that it is possible for a language with a rich, conventional syntax to provide Lisp-style macro power and simplicity. We describe a macro system and syntax manipulation toolkit designed for the Dylan programming language that meets, and in some areas exceeds, this standard. The debt to Lisp is great, however, since although Dylan has a conventional algebraic syntax, the approach taken to describe and represent that syntax is distinctly Lisp-like in philosophy.

This paper includes a pretty interesting overview Dylan's macro system, which is unique in that it's a Lisp-style macro system for an Algol-style language. Which makes sense, since Dylan is really a Lisp-family language. The paper goes on to describe extensions to the Dylan macro system that were used in implementing the Functional Objects Dylan system Functional Developer (formerly Harlequin Dylan).

In a short appendix it also covers Common Lisp and Scheme macros.

There's a big difference between C/C++ preprocessor macros and Lisp macros. C preprocessor macros are text substitution while Lisp macros let you define syntax. Dylans macros let you do that too, allowing you to create new syntax and then use it to improve the expressiveness of your programs.


Dylan
[info]chanson
From the Introduction to the The Dylan Reference Manual:

Dylan is a general-purpose, high-level programming language, designed for use in application and systems programming. Dylan includes garbage collection, type-safety, error recovery, a module system, and programmer control over runtime extensibility of programs.

The name "Dylan" is a portmanteau of the words "dynamic" and "language." Dylan is designed to allow efficient, static compilation of features normally associated with dynamic languages.</p>

There's a lot more information at Gwydion Dylan. I became interested in the language back in the early 1990s, when Apple sent copies of the original book on the original version of the language to any developer that asked.

A lot of top-notch Lisp hackers worked on Dylan, including a lot of people who came from the Lisp machine community. Take a look at these screenshots of a project browser and a class browser from Apple's Dylan environment.

A reasonable way of describing Dylan would be as Scheme plus the Common Lisp Object System (CLOS), cleaned up quite a bit, with a Pascal-style infix syntax. I much preferred it before the change to the infix syntax. It makes code much more needlessly verbose, and it made both the macro system itself and Dylan implementations much more difficult than the original Lisp-style syntax would have.

After reading The Art of the Metaobject Protocol, I have to say that Lisp-syntax Dylan is a much cleaner language than Common Lisp. The price of that is, of course, that Dylan isn't compatible with the existing body of Lisp code, whereas Common Lisp strove for portability.

Like CLOS, Dylan is based on interacting with objects which are instances of classes and are made up of slots. Classes can inherit from other classes, even more than one, and there are fairly straightforward rules describing what happens when inheriting from multiple classes that declare slots with the same name, or from multiple classes that share base classes.

The most significant difference between CLOS and Dylan on one side and Smalltalk and C++ on the other side is that interacting with objects isn't done by sending them messages. Instead, objects are strictly data; they have generic functions applied to them. Generic functions are essentially collections of methods whose arguments are specialized on the classes of the objects they interact with. When a generic function is applied to some objects, the most specific method that is specialized on those objects' classes is invoked; that method can, in turn, invoke the next-most-specific method, and so on.


JavaSchools and Boring, Easy Work
[info]chanson
In The Perils of JavaSchools, Joel Spolsky writes:
Therein lies the debate. Years of whinging by lazy CS undergrads like me, combined with complaints from industry about how few CS majors are graduating from American universities, have taken a toll, and in the last decade a large number of otherwise perfectly good schools have gone 100% Java. It's hip, the recruiters who use "grep" to evaluate resumes seem to like it, and, best of all, there's nothing hard enough about Java to really weed out the programmers without the part of the brain that does pointers or recursion, so the drop-out rates are lower, and the computer science departments have more students, and bigger budgets, and all is well.
Of course, those recruiters don't actually use grep. They have some "fancy" Access database that a "consultant" wrote for them that looks for keywords in Word documents.

In the discussion thread following the article, there has been quite a bit of pushback from people claiming that it's OK that most schools are turning out a lot of mediocre developers, because most software development work is easy and boring and well within their capabilities.

I'm with Joel. This isn't a good thing. Looking past his immediate rant — "teaching all Java means students don't learn recursion and pointers" — I think the three principal things from computer science that every developer must understand are abstraction, algorithms, and architecture. Pointers are architecture. Recursion is algorithms. Functional programming, object-oriented programming, the database relational model, even operating systems, are abstraction.

The reason that I don't think it's OK to have mediocre developers working on mediocre projects is that, in large part, those mediocre projects shouldn't exist. They are exactly the sort of projects that the Software Factories people want to turn into primarily an assembly task. Boring, repetitive, easy software is exactly the sort of software that should be wrapped in domain-specific frameworks, implemented using domain-specific languages, and pretty much abstracted away.

While I may disagree with a lot of their methodologies and the specific instantiations of what they're trying to do, I'm totally with them on that. One of the reasons so much software is so bad is that people keep reinventing the wheel, poorly.

Structure and Interpretation of Computer Programs
[info]chanson
More Scheme learning material, this time appropriate for people who want to learn programming from first principles.

Abelson, Sussman and Sussman's introductory programming course from MIT, Structure and Interpretation of Computer Programs is also available online in its entirety. This includes the book Structure and Interpretation of Computer Programs, its errata, the code from the book, and even sample assignments from the course.

There is even a complete set of video lectures from a version of the course taught by Hal Abelson and Gerald Sussman in 1986. (Of course, they deal with the first edition of the book rather than the second.)

The Scheme Programming Language, Third Edition
[info]chanson
R. Kent Dybvig's book The Scheme Programming Language, Third Edition is available online in its entirety, along with its errata.

This would make good reading for any software developers interested in learning a Lisp-family language. Scheme is nice and consistent, without a lot of the legacy historical baggage that Common Lisp carries (let alone a dialect like Emacs Lisp or Xlisp and its Autolisp variant in Autocad).

Resurgence
[info]chanson
Is it just me, or has the accelerating growth in weblogs, the accelerating growth in computing power, and the accelerating exposure of normal programmers to highly dynamic languages like Perl, Python, and Ruby combined to bring about a resurgence of interest in Lisp?

In preparation of welcoming our new parenthetical overlords, I've been reading The Art of the Metaobject Protocol and over the weekend I installed OpenMCL:
% openmcl
Welcome to OpenMCL Version 1.0 (DarwinPPC32)!
? (require "cocoa")
For more Lisp fun, and a convenient Lisp blog aggregator, check out Planet Lisp.

I think languages that follow the lead of Common Lisp, Dylan, and modern Smalltalk have the most potential as Singularity enablers due to their abstraction and complexity-management features. At some point, I want to write a bit about why they haven't so far seen the kind of uptake that either the C-family languages or the (so-called) "scripting" languages have.

Yes, I know all about Richard Gabriel's Lisp: Good News, Bad News, How to Win Big which gave us the Worse Is Better aphorism. I don't have quite the same take on it though I certainly think Gabriel's perspective is valuable.

Good Reads Online
[info]chanson
A while back, I saw on Lambda the Ultimate that Smalltalk-80: Bits of History, Words of Advice was available online.

There are quite a few more worthwhile language books on the Web. For example, Tim Budd's A Little Smalltalk is also available at Professor Ducasse's site.

You can also find Common Lisp: The Language, Second Edition in various places online, and Paul Graham has made On Lisp available.

I started down this route because I'm reading Graham's Hackers & Painters right now and in some ways it reminds me of Patterns of Software by Richard P. Gabriel which, it turned out, Gabriel posted online once it went out of print.