[racket-dev] generic binding forms

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Mon Aug 26 02:14:08 EDT 2013

Hi Stephen,

> 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.

Your goals seem similar to the ones I had for "bind".
The different binding forms all have binding clauses.
I introduced binding clause transformers that decide what
to do with a given binding clause.

The binding clause transformer :delay can for example
be used like this (where bind is my name for a let that understands
binding clause transformers).

(bind<http://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.html&https://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28form._%28%28lib._bind%2Fmain..rkt%29._bind%29%29>
 ([x :delay<http://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.html&https://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28form._%28%28lib._bind%2Fmain..rkt%29._~3adelay%29%29>
 1]  (+<http://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.html&https://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28def._%28%28quote._~23~25kernel%29._%2B%29%29>
 x x)))

At macro expansion time this is expanded into

(let<http://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.html&https://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28form._%28%28lib._racket%2Fprivate%2Fletstx-scheme..rkt%29._let%29%29>
 ([x (delay<http://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.html&https://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28form._%28%28lib._racket%2Fpromise..rkt%29._delay%29%29>
 1)])  (let-syntax<http://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.html&https://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28form._%28%28lib._racket%2Fprivate%2Fletstx-scheme..rkt%29._let-syntax%29%29>
 ([clause ...<http://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.html&https://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._......%29%29>
])    (+<http://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.html&https://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28def._%28%28quote._~23~25kernel%29._%2B%29%29>
 x x)))

where clause ... introduce a syntax binding such that x in the body
expands to a use of x.

This is just an example though. The key concept is the binding clause
transformer.
Here is the documentation for bind and def (let and define):
http://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.html

Here is the Github repository:  https://github.com/soegaard/bind

Another small example:

Example:                                                       > (bind
([v :vector (for/vector ([i 5]) (random 10))])
    (displayln (~a "The vector " v " contains " v))
    (displayln (~a "The first element is: " (v 0)))
    (v! 0 42)
    (displayln (~a "The first element is now: " (v 0)))
    (displayln (~a "The middle three elements are: " (v 1 4))))


This expands into uses of vector-ref and vector-set! so there is no runtime
penalty
for using this shorthand.

/Jens Axel


2013/8/26 Stephen Chang <stchang at ccs.neu.edu>

> 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
>



-- 
-- 
Jens Axel Søgaard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/dev/archive/attachments/20130826/d0f2509b/attachment-0001.html>

Posted on the dev mailing list.