Gauche

I just discovered Gauche Scheme. I have been looking for a Lisp/Scheme dialect for my latest pet project, and it seems this is just what the doctor ordered.

  • It’s cross-platform (Unixoid systems and Windows)
  • Builds out of the box on Mac OS X, even on my old G3
  • Supports both hygienic and “dirty” macros
  • Comes with an object system
  • Comes with a bunch of libraries out of the box (like a HTTP library, which is one of the things I needed)
  • Works with SLIB; in fact, if SLIB is already installed, it will find it and integrate it
  • Supports a large number of SRFIs

Chicken has most of this too, except it lacks Windows binaries, and it recently got rid of unhygienic macros. Libraries can be installed as eggs, of course, so it might not need SLIB.

Anyway, said “pet project” involves making HTTP GET calls, and requires a powerful object system. (More about this later, if it ever becomes usable.) I wanted to use a Lisp/Scheme dialect for flexibility, and I wanted it to be cross-platform if at all possible, so users can run it on Windows as well. It turned out that it was remarkably hard to find a Scheme that matched all these requirements. I will not go into all the problems that I encountered, but suffice to say that Gambit, Scheme48, PLT and Petite Chez Scheme all had their own issues. (That is not to say that I won’t use them for other projects…)

That said, I might still change my mind and use Common Lisp instead… :-)

7 Comments

  1. Peter Bex said,

    May 22, 2010 @ 6:49 am

    Gauche is pretty cool, I agree. However, there’s one thing I believe you’re unfair about:

    You cite the existence of (purely) unhygienic as an advantage, but actually it is a disadvantage. The hygienic macro system Chicken uses is a low-level macro system which allows you to break hygiene as you choose. It is *more* powerful than the old define-macro, not *less* powerful! (define-macro has unfixable issues with lexically shadowed function and macro names, explicit renaming macros don’t have this problem)

    If you’d like to learn more, feel free to drop by in #chicken on IRC.

    Furthermore there’s a http-client egg I wrote for Chicken as well as spiffy, a webserver library, which I maintain :)

  2. Peter Bex said,

    May 22, 2010 @ 7:06 am

    To benefit those reading along, here’s a trivial example of how define-macro fails and Chicken’s explicit renaming macros win (I hope this will be formatted properly…):

    $ gosh

    gosh> (define-macro (mylambda . args) (cons ‘lambda args))

    #<undef>

    gosh> ((mylambda (a) (+ a 1)) 2)

    3

    gosh> (let ((lambda ‘hi)) ((mylambda (a) (+ a 1)) 2))

    *** ERROR: unbound variable: a

    Stack Trace:
    _______________________________________
    0 (a)

    At line 4 of “(stdin)”

    1 (+ a 1)

    At line 4 of “(stdin)”

    gosh> (exit)

    $ csi

    #;1> (define-syntax mylambda (lambda (exp ren cmp) (cons (ren ‘lambda) (cdr exp))))

    #;2> ((mylambda (a) (add1 a)) 2)

    3

    #;3> (let ((lambda ‘hi)) ((mylambda (a) (+ a 1)) 2))

    3

    #;4> (exit)

    I agree this is a silly and contrived example, but imagine what happens with bigger macros which use lots of helper functions or helper macros. The chances that one of those function or macro names happens to be used in a surrounding LET expression is increasingly large in those cases, and then you’re out of luck.

    In Common Lisp (where defmacro originated) this is much less of a problem because it’s a Lisp-2, where macros and functions don’t share their namespace with variables, so there’s no way a LET can shadow the lambda or functions used in the macro. However, if it *does* fail it’ll probably be a lot harder to debug!

  3. Peter Bex said,

    May 22, 2010 @ 7:21 am

    Oh, and an example that shows you can break hygiene just as easily: (this macro defines a variable named foo-WHATEVER with the value as defined)

    $ gosh

    gosh> (define-macro (prefix-foo name value)

    (list ‘define (string->symbol (string-append “foo-” (symbol->string name))) value))

    gosh> (prefix-foo test 1)

    gosh> foo-test

    1

    gosh> (exit)

    $ csi

    #;1> (define-syntax prefix-foo

    (lambda (exp ren cmp)

    (list (ren ‘define) (string->symbol (conc “foo-” (cadr exp))) (caddr exp))))

    #;2> (prefix-foo test 1)

    #;3> foo-test

    1

    #;4> (exit)

    As you can see, there’s very little difference between the old and the new system.

  4. Hans Nowak said,

    May 22, 2010 @ 12:38 pm

    Thanks for the explanation, Peter.

    The reasons I was happy to find Gauche are actually somewhat superficial. :-)

    I have been wanting to write a game server which can be used to play Magic the Gathering (or other card games) over the internet. I wanted to use a variant of Lisp or Scheme, since I need a flexible language to model all the cards and rules. I also wanted some of my friends to be able to run it without much trouble, so I needed something with Windows binaries, which Gauche happens to have at the moment, while Chicken does not. The fact that Gauche has a bunch of libraries out of the box was very useful too, because it means that people don’t have to download and install (and maybe compile) eggs just to play the game.

    So those are some of the reasons why Gauche seemed like a better fit *for this particular project*.

    As for the macros, I have some legacy code that uses old-style macros, and I didn’t want to be forced to rewrite them just yet.

    Still, your macro examples are very useful, since I don’t think I understand Scheme macros all that well just yet.

    Bedankt,

    –Hans

  5. Peter Bex said,

    May 22, 2010 @ 1:47 pm

    I agree the Windows situation isn’t too great in Chicken, but people have been working steadily on that and I think the situation has improved a lot over the last months. But I don’t use Windows, so that’s just hearsay :)

    How do you handle graphics/GUI support in Gauche? Doesn’t that require some kind of extension?

    You probably want to read http://chicken.wiki.br/man/4/Deployment by the way; this allows you to write self-contained executables which can make use of as many extension libraries (eggs, not just core) as you want :)

    About those legacy macros:

    (define-syntax define-macro

    (syntax-rules ()

    ((define-macro (name . args) body …)

    (define-syntax name (lambda (exp ren cmp) (apply (lambda (name . args) body …) exp))))))

    This will make define-macro “just work”. It won’t make your macros hygienically correct, but they weren’t that to start with, so that’s not something to worry about for now :)

  6. Hans Nowak said,

    May 22, 2010 @ 4:58 pm

    “How do you handle graphics/GUI support in Gauche? Doesn’t that require some kind of extension?”

    Yes :-) But I don’t need it for this project. The server (non-GUI) would be written in Gauche. The client (through which people play the game) is written in Python. :)

  7. Hans Nowak said,

    May 22, 2010 @ 5:09 pm

    … Looking back at this post, I think I actually just needed an excuse to try another Scheme. :-)

RSS feed for comments on this post