Will.Whim

A weblog by Will Fitzgerald

First experiment with Arc

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
red

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
red

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.

Advertisements

10 responses to “First experiment with Arc

  1. Nathan Sanders February 1, 2008 at 12:47 pm

    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 _)]
    results)))
    (pr …)
    (if (is totals goods) ‘green ‘red))

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

  2. Will February 1, 2008 at 2:35 pm

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

  3. Will February 1, 2008 at 3:29 pm

    Now it catches errors, too.

  4. Nathan Sanders February 1, 2008 at 3:38 pm

    Do you mind if I post this code (modified) to the git repository arc-wiki? (The announcement is at http://www.arclanguage.org/item?id=809)
    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))
    t))
    (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)))))

  5. Cat Dancer February 1, 2008 at 9:00 pm

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

    can be written as

    [caris _ key]

    (see caris in arc.arc) ^_^

  6. Will February 1, 2008 at 11:31 pm

    Cool. Thanks!

  7. Lukas February 3, 2008 at 4:30 pm

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

  8. Virgil February 8, 2008 at 2:30 am

    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?

  9. Marcin Tustin February 8, 2008 at 8:57 am

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

  10. Will February 8, 2008 at 5:47 pm

    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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: