First experiment with Arc

February 1st, 2008 | by Will |

I decided to try to write a simple but useful program in Arc, the programming language recently released by Paul Graham.

One thing I’ve liked about using Ruby is a testing framework called Rspec, in which you describe the behavior of your program in a kind of narrative form. So I decided to try and write a similar system for Arc.

Here’s an example of a specification that tests three of Arc’s list operations. The last specification will fail in this example. Wordpress is going to screw up indentation; there’s not much to be done about it.

(describe "Testing basic Arc list operations"

  (it "should support CAR"
        (is (car '(a b c)) 'a))

   (it "should support CDR"
      (iso (cdr '(a b c)) '(b c)))

    (it "should get this test wrong"
        (acons (car nil)))))) 

Note that is, iso and acons are Arc’s versions of Lisp’s eq, equalp and consp.

When you evaluate this specification and print the results, you get:

;; Testing basic Arc list operations
;; should get this test wrong: nil ((acons (car nil)))
;; Tests: 3; Good: 2. Pct: 66.66

The result is either ‘red’ (at least one test failed) or ‘green’ (all tests passed).

Each ‘it’ clause is a specification test; and optional clauses allow you to specify a ‘prolog’ to run before all the tests, an ‘epilog’ to run after, and setup and teardown clauses to run before and after each test. As a simple example:

(describe "Testing basic Arc list operations"
    (prolog (pr "\n;; This is the prolog\n"))
    (epilog (pr ";; This is the epilog\n"))
    (setup (pr ";; Setting up\n"))
    (teardown (pr ";; Tearing down\n"))
    (it "should support CAR"
        (is (car '(a b c)) 'a))
    (it "should support CDR"
        (iso (cdr '(a b c)) '(b c)))
    (it "should get this test wrong"
        (acons (car nil))))))

With a test result of:

;; This is the prolog
;; Setting up
;; Tearing down
;; Setting up
;; Tearing down
;; Setting up
;; Tearing down
;; This is the epilog
;; Testing basic Arc list operations
;; should get this test wrong: nil	((acons (car nil)))
;; Tests: 3; Good: 2. Pct: 66.66

You can find the code at spec.arc.

Things I liked about writing this program and Arc in general:

  1. It’s very nice to have real macros again, not Ruby’s sort-of macroish text re-evaluation.
  2. To collect all of the it clauses, I wrote a function called assocs, and I liked the way Arc allows you to write anonymous functions. Here's the definition:
    (def assocs (key list) (keep [and (acons _) (is (car _) key)] list))
    The anonymous function is between the square brackets.
  3. I think I could come to like the short names Graham has chosen.
  4. I like to imagine that this is one of the first Arc programs not written by Graham or Morris.
  5. Although I didn’t write it, it would be trivial to add HTML output as a different format.

Some things that Arc really does need and I missed in writing this code:

  1. A standard structure object (and vectors). Over half my code is spent in writing list accessors. Fortunately, these are easy to write.
  2. Error objects and error handling! It’s hard to believe there is none yet.
  3. The usual code writing things: tracing, edit modes, unit testing tools — oh, wait, I just wrote that.

I don’t know how successful Arc will be. Certainly it will need lots of standard libraries, pervasive Unicode string handling, etc., if it is to move beyond it’s current state (and to Graham’s credit, he’s not claiming any more for ‘Arc0′ than is there). But it is nice to be able to program in a Lisp again.

  1. 10 Responses to “First experiment with Arc”

  2. By Nathan Sanders on Feb 1, 2008 | Reply

    Thanks for the code. I haven’t used Ruby’s testing framework and it looks nicer than the XUnit ones.

    A couple of comments: is there a reason you defined your accessors as

    (def spec-desc (spec) (first spec))

    instead of

    (= spec-desc first)

    The print name of spec-desc is nicer the first way, I guess.

    Also, I think the map [do ...] idiom is just each … .
    I would probably write that segment as

    (let results (results-results results)
    (= totals (len results))
    (= goods (len (keep [do
    (when (or all (no (result-value _)))
    (pr ...))
    (result-value _)]
    (pr …)
    (if (is totals goods) ‘green ‘red))

    Sorry about the indenting if it doesn’t come through.

  3. By Will on Feb 1, 2008 | Reply

    Thanks! I didn’t see each (tho’ it was clearly there in the tutorial). Changes have been made at spec.arc.

  4. By Will on Feb 1, 2008 | Reply

    Now it catches errors, too.

  5. By Nathan Sanders on Feb 1, 2008 | Reply

    Do you mind if I post this code (modified) to the git repository arc-wiki? (The announcement is at
    I wrote a struct macro and used that to shorten the accessor code:

    (mac struct (type . fields)
    (with (deftype (sym:string “def-” type)
    type-check (uniq)
    struct (uniq))
    `(let ,type-check (fn (,struct)
    (if (or (~acons ,struct) (~sym (car ,struct)))
    (warn “Doesn’t appear to be a struct” ,struct)
    (~is (car ,struct) ‘,type)
    (warn “Struct is wrong type” (car ,struct))
    (def ,deftype (,@fields)
    (list ‘,type ,@fields))
    ,@(map (fn ((i field))
    (with (get (sym (string type “-” field))
    gobj (uniq))
    `(def ,get (,gobj)
    (when (,type-check ,gobj)
    (,gobj ,(+ 1 i))))))
    (enum fields)))))

  6. By Cat Dancer on Feb 1, 2008 | Reply

    [and (acons _) (is (car _) key)]

    can be written as

    [caris _ key]

    (see caris in arc.arc) ^_^

  7. By Will on Feb 1, 2008 | Reply

    Cool. Thanks!

  8. By Lukas on Feb 3, 2008 | Reply

    Interesting post. Makes me want to play with arc myself.

  9. By Virgil on Feb 8, 2008 | Reply

    I don’t understand the enthusiasm over arc. You say you’re now able to program in a Lisp again, but we’ve had mature free scheme implementations for years now which have the missing features you listed and are just a few macros away from the syntax of arc (based on the arc I’ve seen so far). What is it about arc that has gotten you back into Lisp?

  10. By Marcin Tustin on Feb 8, 2008 | Reply

    I’d like to ask the same question as Virgil: why not scheme or lisp on your favourite platform?

  11. By Will on Feb 8, 2008 | Reply

    Oh, I only meant that I’ve been writing a lot of Ruby, and it was fun to write in programming language with ‘real’ (ie more powerful) macros.

Sorry, comments for this entry are closed at this time.