[racket-dev] generic binding forms

From: Stephen Chang (stchang at ccs.neu.edu)
Date: Mon Aug 26 00:54:34 EDT 2013

Hi dev,

I've noticed that Racket has a lot of convenient binding forms but
they don't fit together unless someone does it manually (for example
there's match-let and match-let-values, but no match-for).

As an educational side project, I've been toying around with a
different way of organizing all the binding forms. What I wanted to do
is remove the need to manually combine current (and future) binding
forms by moving the binding "logic" to the binding site itself.

Inspired by the in-vogue generics movement in the Racket world, I've
hacked together a sort of "generic interface" for bindings (in
reality, it's just a bunch of syntax properties right now), and
implemented alternate versions of some of the main binding forms that
support "instances" of these generic bindings.

To illustrate, here are some test cases for a generic define I
implemented (~define). I also implemented binding "instances" for
match and values (which I arbitrarily named $ and ~v below) and I can
use these forms in (mostly) any binding position that supports generic
bindings.

;; functions
> (~define (f1 x y) (+ x y))
> (f1 10 20)
30
> (~define (f2 ($ (list x y))) (+ x y))
> (f2 (list 10 20))
30

;; non-functions
> (~define a1 100)
> a1
100
> (~define (~v a2 a3) (values 134 456))
> a2
134
> a3
456

You can nest bind instances too:

> (~define (~v ($ (list b1 b2)) b3) (values (list 22 33) 44))
> b1
22
> b2
33
> b3
44

Does anyone think this is useful? Or is it just a lot of work to save
a little bit of typing? Has anyone tried something like this before?

It's still very much a work in progress but I figure I would ask for
some feedback earlier rather than too later, in case there is
something that makes this infeasible.

Brave souls can look at the hackery here:
https://github.com/stchang/generic-bind/blob/master/generic-bind.rkt
(Warning: I'm still trying to figure out all the toys in the Racket
macro toolbox. For the most part, everything still looks like a
syntax-rule/case/parse/->datum nail to my hammer.)

Technical question: I couldn't figure out a nice way to implement
~let. Essentially, I want a let form where some clauses are let-values
and some are match-let, but I need to bind them all at the same time,
like let. I can't define a ~lambda that works with values because
functions in racket can't receive values. Anyone have any ideas?

Side observation: Trying to get things to work with multiple return
values was a pain because they don't compose (as in, functions can
produce them but can't receive them). Not sure if anything can be done
about this though.

Posted on the dev mailing list.