» Publishers, Monetize your RSS feeds with FeedShow: More infos (Show/Hide Ads)
Someone should make a mirror because I can't figure out how to download my posts!
Then one guy had the audacity to say this:
"Okay pg, it's time to call you out. Unicode support is not trivial, like you make it out to be, and it's not a waste of time. It's a critical piece of infrastructure for any runtime. You fail."
Then came the knockout punch. Patrick Collison of CROMA fame added full Unicode support to Arc by adding -2 (that's minus two!) lines to Arc! Mr. Graham came out with this followup to the above sass:
"I'm glad this is preserved for posterity, since it did turn out to be trivial and in fact got added with about -2 lines of code a few days after this comment was posted..."
It's no joke. Unicode required removing things from Arc, not adding it! That's how damn elegant the language is! And the support is much simpler than it is in other, less elegant, more gross programming languages. For example, here's the entire definition of "upcase":
(def upcase (x)
(let upc (fn (c)
(let n (coerce c 'int)
(if (or (< 96 n 123) (< 223 n 247) (< 247 n 255))
(coerce (- n 32) 'char)
c)))
(case (type x)
string (map upc x)
char (upc x)
sym (sym (map upc (coerce x 'string)))
(err "Can't upcase" x))))
Other languages have to deal with databases, which are inherently slower and bureaucratic. Viaweb used zero databases!
(incf (gethash table key 0))
The wacky historical names make it hard to tell (incf? come on, ANSI!), but it increments the table entry for key in table. If key is not in table it uses a default value of 0, adds one to it, and stores it back in the table.
Arc does not have this onion. Instead, you see this elegant style used again and again in the arc sources:
(= (table key) (+ 1 (or (table key) 0)))
As you can see, this is much shorter (just line up the code above with this code). Partly because the symbols are very short; aside from the table and key name, the only arc symbols needed are =, +, 1, 0, and or. There is almost a mathematical purity to those symbols. It reminds me of the famous equation: e^pi i - 1 = 0.
First of all, Arc is a compiler. This is a boon. There are too many toy Lisp interpreters out there already. It compiles the Arc language to a lesser language. In this case, the lesser language is Scheme, but that's just an implementation detail. I'm sure these Arc will be ported "to the metal" (or is that "to the meta"? ha ha!) soon enough by an enterprising student who doesn't listen when the master says it can't be done, just like John McCarthy and the student who ported Lisp to the metal. That guy.
Another remarkable thing about Arc is what Mr. Graham has been able to strip away. He has gotten down to the essence of the language. Everything else can be added on. Common Lisp is incredibly and unnecessarily complex, so by stripping things off you can get a lot of power and flexibility. For example, you can take Common Lisp. Then take away packages, specialized vectors, CLOS objects (OO, ugh!), structures, complicated lambda lists, complicated streams, generic functions, a tree shaker, delivery options, native code generation, Emacs integration, the potential for a commercial IDE, arglist hints, symbol completion, Unicode support, debuggers, profilers, inspectors, GUI tools, and a lot of other cruft.
What you are left is is the bare essense of coding. Everything written is essential. Nothing is superfluous. There are truly no onions. The specification of Arc (which is the implementation of Arc) can be printed on just a few pages (full duplex); the whole thing is 4609 lines of code!
Let's be clear. Paul Graham is the #1 Lisp luminary right now. When he writes that he is a typical Lisp hacker, it's also 100% true. But there's another factor. He's typical, to the nth degree. When he says Lisp needs to go in a new direction, people who know nothing about Lisp will sit up and listen. It's his kind of leadership that will bring Lisp back into the mainstream.
This blog post is a little long. I'll leave you with the axioms of the new Lisp world:
(define (ac s env)
(cond ((string? s) (string-copy s)) ; to avoid immutable strings
((literal? s) s)
((eqv? s 'nil) (list 'quote 'nil))
((ssyntax? s) (ac (expand-ssyntax s) env))
((symbol? s) (ac-var-ref s env))
((ssyntax? (xcar s)) (ac (cons (expand-ssyntax (car s)) (cdr s)) env))
((eq? (xcar s) 'quote) (list 'quote (ac-niltree (cadr s))))
((eq? (xcar s) 'quasiquote) (ac-qq (cadr s) env))
((eq? (xcar s) 'if) (ac-if (cdr s) env))
((eq? (xcar s) 'fn) (ac-fn (cadr s) (cddr s) env))
((eq? (xcar s) 'set) (ac-set (cdr s) env))
; this line could be removed without changing semantics
((eq? (xcar (xcar s)) 'compose) (ac (decompose (cdar s) (cdr s)) env))
((pair? s) (ac-call (car s) (cdr s) env))
(#t (err "Bad object in expression" s))))
YAY!!!
I can tell that switching from BruceLisp to Arc will be like slipping into an old, familiar, elegant boot!
So what's on my mind? The same themes that have puzzled Lisp enthusiasts for decades!
1. Macros -- I always come back to Macros with Lisp. Along with tail recursion, it's the way that Lisp stands out from other languages.
2. Closures -- another feature unique to Lisp, closures are basically object orientation...done right! No more spaghetti code with so-called classes, objects, etc. You can just get all the functionality you need by deftly weaving closures together. As you may know, spaghetti doesn't weave. It snaps or is just too greasy to hold together. Lisp closures are more like thread. (But not like threads, which are another barbaric construct.)
That's it for now...I'll write more later!
Other languages do this too, such as python with its dir() function and ruby with the ruby shell. Perl also has the debugger, which is a great interactive perl shell too.
A big downside of Common Lisp is the size of its specification. Scheme's spec is 50 pages. Lisp's spec is over 1000! There's an old joke: how many common lispers does it take to change a light bulb? One, he just stands on the spec, reaches up, takes out the bulb, puts in a new one, and the light's changed. By that, I mean the spec is pretty big.
But the good thing is that you rarely have to read it. If you want to know how a function works, just experiement! Here's an example. I want to get random numbers. So I just start by typing a bit:
CL-USER> (ran <-- cursor is here
Then I push TAB, and out pops "random"! Lisp is great that way! But how does random work? Easy, let's just experiement a little:
CL-USER> (random 10)
0
CL-USER> (random 10)
5
CL-USER> (random 10)
1
From that short experiment it's easy to see that random is a lisp function that returns a random integer between 0 and 1/2 its argument (in this case 5, which is 10 times 1/2). Why they picked 1/2 I don't know, but you can always multiply by 2 if you want to do something like select a random element from a directory. There are also some web services that will return random numbers. I don't have all the answers, get creative!
1. Obviously, macros have to get the top billing. Macros are like little compilers. They take your source code, do some transformations, and turn it into unreadable CPU-specific code that is blazing fast. For example, (defmacro my_plus (&rest; args) (apply '+ args)). You don't have that kind of flexibility in other languages (except C with some inline ASM, but Lisp gives you more abstractions to work with (also C suffers from the too-fast problem, but that's a different blog post (oh no, look at the parentheses (can you tell I love lisp? :))))))
2. Pathnames
3. The ability to make your own object system at will. This is partly an advantage of macros but I need to come up with at least a few good points.
4. Elegance & grace of some parts (if you avoid the unelegant parts). For example, the ability to rename defun to define and make it more logical and memorable in the process.
Can you think of more? Please share in a comment...and let's keep it positive, please!
So why Lisp? And why Common Lisp? The alternatives are worse.
- Python - this one is easy. Slow, whitespace sensitive.
- Perl - hard to read. Good mix of fast and slow.
- Ruby - too slow.
- C - hard to read, too fast
- C++ - hard to read
The source code for the site is not available, but based on Mr. Graham's past writing I can imagine the elegance. Instead of writing a bunch of code to display pages, it is likely a symphony of Little Language construction. This Little Language (built in Arc) is customized very precisely for the problem at hand. Then all the tasks in the application boil down to actions expressed in the most concise, powerful way possible.
Of course I cannot be sure, but I bet the exclamation point on the end of the Startup News sentence is this tour de force of brevity, concision, and domain specificness:
(mkreddit frontpage-downvotes: #false)
Mr. Graham can confirm or deny in the comments, if he deigns.
The author of these two pieces gets into a key issue for Lisp: intuitiveness. I wonder if he's aware of Bruce's First Law of Lisp?
There may be some of the lispers who taken with power decide their view is "over the horizon" and yet perfect, without adaptability, and thus must take all others as "contrary, foolish, and without merit" -- yet to do so, premature, invites bickering.
Yet it is an accident mostly, yet they do not see it thus, but the collision of "reality" must show the "design, of a thing" a failure or success, by chance.







