Re: [racket-dev] generic binding forms
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 time. 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 matth...@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 _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] generic binding forms
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). (bindhttp://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.htmlhttps://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28form._%28%28lib._bind%2Fmain..rkt%29._bind%29%29 ([x :delayhttp://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.htmlhttps://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.htmlhttps://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 (lethttp://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.htmlhttps://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28form._%28%28lib._racket%2Fprivate%2Fletstx-scheme..rkt%29._let%29%29 ([x (delayhttp://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.htmlhttps://github.com/soegaard/bind/blob/master/scribblings/bind.html=false#%28form._%28%28lib._racket%2Fpromise..rkt%29._delay%29%29 1)]) (let-syntaxhttp://htmlpreview.github.io/?https://github.com/soegaard/bind/blob/master/scribblings/bind.htmlhttps://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.htmlhttps://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.htmlhttps://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 stch...@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
Re: [racket-dev] generic binding forms
On Sun, Aug 25, 2013 at 10:54 PM, Stephen Chang stch...@ccs.neu.edu 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'd introduce new names to bind them in sequence and then rename everything after it's all available. My letwreck does something similar: http://jeapostrophe.github.io/2013-08-05-letwreck-post.html#%28elem._%28chunk._~3cletwreck-defn~3e~3a1%29%29 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 -- Jay McCarthy j...@cs.byu.edu Assistant Professor / Brigham Young University http://faculty.cs.byu.edu/~jay The glory of God is Intelligence - DC 93 _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] generic binding forms
I've been wanting a match-for for quite some time, but there are design decisions to be made in such cases. Non-linear patterns are tricky to coordinate - should all clauses of a for/fold be considered part of the same match pattern? How about for*/fold? (My opinions are yes then no). If you have several binding forms that would work together in this way, and not just match patterns, then what is the proper way to set up and interact with such scopes? Do we need something as involved as an internal definition context? I'll take a closer look at your repo when I come into the lab today. -Ian - Original Message - From: Jay McCarthy jay.mccar...@gmail.com To: Stephen Chang stch...@ccs.neu.edu Cc: dev dev@racket-lang.org Sent: Monday, August 26, 2013 8:27:06 AM GMT -05:00 US/Canada Eastern Subject: Re: [racket-dev] generic binding forms On Sun, Aug 25, 2013 at 10:54 PM, Stephen Chang stch...@ccs.neu.edu 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'd introduce new names to bind them in sequence and then rename everything after it's all available. My letwreck does something similar: http://jeapostrophe.github.io/2013-08-05-letwreck-post.html#%28elem._%28chunk._~3cletwreck-defn~3e~3a1%29%29 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 -- Jay McCarthy j...@cs.byu.edu Assistant Professor / Brigham Young University http://faculty.cs.byu.edu/~jay The glory of God is Intelligence - DC 93 _ Racket Developers list: http://lists.racket-lang.org/dev _ Racket Developers list: http://lists.racket-lang.org/dev
Re: [racket-dev] generic binding forms
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 _ Racket Developers list: http://lists.racket-lang.org/dev
[racket-dev] generic binding forms
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