[plt-scheme] Yet another cute idea

From: Eli Barzilay (eli at barzilay.org)
Date: Fri Sep 27 16:20:19 EDT 2002

The subject line is a fair warning -- I have yet another semi-wild
idea.  The thing is that this one is useful in practice, something
implementable, although it will take me some time...  Of course, this
doesn't prevent me from writing another huge email.

So last night I was wondering through the Python tutorial, just
because I've heard that it was supposed to be better than Perl etc.
There is one single feature that it has, that Scheme doesn't but I
really wish it had, and that most modern language I hear about have as
well (ML, Haskell, and yes, even Perl).  This feature is usage of
pattern matching to introduce new bindings, probably the one I miss
most from ML.  The only Scheme solution is using multiple values, but
the fact that value tuples are not first-class objects makes it a poor
man's solution.

And that got me thinking about how I'd implement it in [Mz]Scheme.
Currently, in Swindle, I have two sets of tweaking -- the first one
makes name definitions uniform -- since this works in Scheme:

  (define (foo x) (+ x 1))

I made this work too:

  (let (((foo x) (+ x 1))) ...)

But I also made this work for nested functions:

  => (define ((foo x) y) (+ x y))
  => foo
  #<procedure:foo>
  => (foo 10)
  #<procedure:foo:1>
  => ((foo 10) 20)
  30
  => ((let ((((foo x) y) (+ x y))) (foo 3)) 5)
  8

The second tweak are generic setters:

  => (define a (list 1 2 3))
  => (set! (cadr a) 22)
  => a
  (1 22 3)

`(set! (foo ...) ...)' just transforms its body into a usage of
`set-foo!' (following an idea from Eric Kidd, who followed Dylan), and
produces the nice feature of allowing `set-foo!' to be either a syntax
or a function, and of being able to do this:

  => (let ((foo car) (set-foo! set-car!)) (set! (foo a) 11))
  => a
  (11 22 3)

[BTW, for the purists, I've avoided the SRFI-17 flamewar by making the
`setf' module provide `setf!', which is later renamed as `set!', so it
is possible to use two seperate bindings if you don't want to get
confused.]

Now, yet another functionality I have, is a pattern matcher, which
allows you to do things like:

  => (match '(1 (2 3 4)) ((x (y z . r)) (list x y z r)))
  (1 2 3 (4))

But I don't like it much -- mainly because it is a big piece of syntax
which is not homogeneously mixed in Scheme.

What I would like is somehow combine all these things into a single
feature that will allow me to use pattern matching.  Now back to what
I realized I could do when I was thinking about Python.  The thing is
that the generic `set!' knows what to do when it is used with an
*accessor*: the syntactic mapping from `car' to `set-car!' allows it
to correctly handle `(set! (car x) y)'.  Now, what could be the
meaning of using a *constructor* instead?  -- It could be used for
pattern matching!  For example, I would expect something like this to
work:

  => (set! (list a b) (list 8 9))
  => (list b a)
  (9 8)

This is implemented by defining a `set-list!' syntax which is
analogous to the built-in `set!-values' (but implemented using
`pset!', which is part of my `setf' module).  This means that things
like this also work:

  => (set! (list a (list b c)) '(7 (8 9)))
  => (list a b c)
  (7 8 9)

and that to get a better pattern "look", this can also be made to
work:

  => (set! `(,a ,b) `(7 8))

And if at some point (*cough*) list syntax objects will contain
information about the original characters, you could make `{...}'
stand for `(#%app list ...)' (e.g, by defining an #%curly-brace
macro), and then you could

  => (set! {a b} {7 8})

Anyway, the big problem with this is that `define' and `let' really
doesn't work like the generic `set!' -- because either this

  (define (car x) ...)

sets the car slot of x, or

  (set! (car x) ...)

sets `car' to a new function.

Obviously, the way things are now makes sense -- there is no point in
`defining' slots of objects, and there is little point in setting a
function value using the short form.

So now I'm finally getting to the way I think I'll implement it.  The
thing which is needed is some facility to define `patterns' which
should be a combination of a syntax value and a run-time value.  For
example, `list' is the normal list function, but there is also
syntactic information on how to use `list' as a pattern.  This means
that `set!' can use it to make `(set! (list ...) ...)' work as above,
but also `define' and `let' should be able to handle it as a binding,
by destructuring the given argument.  Of course, doing this means that
`list' cannot be redefined using the short syntax since defining
`(list x y)' will actually define `x' and `y' to given values, but it
should be possible to redefine list using the standard notation.

That's all for now.  The rest will come when I find time to get
something working.

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!


Posted on the users mailing list.