[racket-dev] generic binding forms

From: Stephen Chang (stchang at ccs.neu.edu)
Date: Thu Aug 29 02:18:32 EDT 2013

Thanks for all the feedback everyone.

There seems to be some interest so I've uploaded my generic binding
forms to planet2: https://pkg.racket-lang.org/info/generic-bind

I realize it's the pre-semester crunch, but if anyone wants to try it
out, I would be grateful for any feedback.

Here are some docs: http://stchang.github.io/generic-bind/generic-bind.html

I've implemented new versions of the following forms to support my
"generic bindings": define, lambda, let, let*, letrec, and all the
for/ and for*/ forms (my versions are prefixed with "~").

These forms *should be* drop-in replacements for their Racket
counterparts. For example, my ~for/?? and ~for*/?? forms pass all the
(non-buggy) for/ tests in the racket test suite.

This library is intended to be a proof-of-concept, so I have not
measured things like performance at this time. I'm pretty sure my for/
forms are much slower than the existing implementation and using my
binding forms will likely contribute a noticeable increase in compile

Regarding Ian's comments, I decided that there should not be any
interaction between let binding clauses, other than the standard
behavior of let, let*, and letrec. This means that if there are
duplicate identifiers in different match patterns in different
clauses, it will behave like duplicate identifiers in let, let*, or
letrec, and *not* like match-let. The same is true in my for/ forms.

Finally, I think my macros are pretty amateur hour and I often feel
that there must be better ways to do certain things that I just am not
aware of, so if any gurus are interested in lending some time for a
code walk, I would be very appreciative.

On Mon, Aug 26, 2013 at 6:58 PM, Matthias Felleisen
<matthias at ccs.neu.edu> wrote:
> What are the performance implications of this design? Specifically how do overlapping uses fare in the two systems? Microbenchmarks okay for now. -- Matthias
> On Aug 26, 2013, at 12:54 AM, Stephen Chang wrote:
>> 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.
>> _________________________
>>  Racket Developers list:
>>  http://lists.racket-lang.org/dev

Posted on the dev mailing list.