Like others have mentioned, my generic-bind package has the functionality you want but is still in the experimental stages. For small programs, the generic-bind for/_ forms are about as fast as the current Racket implementation but expect 2-3x slowdown for larger programs.
On Tue, Sep 3, 2013 at 10:54 AM, J. Ian Johnson <i...@ccs.neu.edu> wrote: > Asumu's suggestion is what I would use, since generic-bindings are currently > unstable and not as performant as the idiomatic manual solutions. > A difficult idiom to encode, however, is when you want to skip elements of > the sequence that don't match, since you end up needing define forms between > for-clauses, as well as some "doesn't match" value that you give to all > would-be defined identifiers, and add #:unless (eq? first-match-id > doesnt-match). Not only can you not even do that, getting it to work in the > current for-forms would require extra allocation (say, putting all matching > identifiers in a list, or #f if no match) and additional nesting of for > forms, which ruins the convenience of the for/X macros. We can't express > [(list a b) (in-list list-of-2lists)] as a special form that uses :do-in, > since match shouldn't have to know how in-list decomposes its sequence. > > Instead, I would propose an extension of the for macro collection itself, > such that the built looping structure is generalized to something like > > (let-outer-form ([outer-pattern outer-expr] ...) > outer-check > (let-pre-loop-form ([pre-loop-pattern pre-loop-expr] ...) > (let-loop-form loop ([loop-pattern loop-expr] ...) > (if pos-guard > (let-inner-form ([inner-pattern inner-expr] ...) > (if pre-guard > (let body-bindings > (if post-guard > (let-reloop-form ([reloop-pattern reloop-expr] ...) > (loop loop-arg ...)) > done-expr)) > done-expr)) > done-expr)))) > > Notice the new pre-loop and reloop binding opportunities. I've found myself > wanting to compute some values that would otherwise have to be recomputed or > hackily stored somewhere in order to use in loop-expr ... and loop-arg ... > > for has the following instantiation > [let-outer-form let-values] > [(outer-pattern ...) ((outer-id ...) ...)] > [let-pre-loop-form let] > [(pre-loop-pattern ...) ()] > [(pre-loop-expr ...) ()] > [let-inner-form let-values] > [(inner-pattern ...) ((inner-id ...) ...)] > [let-reloop-form let] > [(reloop-pattern ...) ()] > [(reloop-expr ...) ()] > > Now I say "something like" since this looping structure is built for the > entire collection of for-clauses, and not just one. Thus, there needs to be a > sensible protocol for special clause forms to be combined in the different > generalized forms. We could have our own > outer-form/pre-loop-form/let-loop-form/let-inner-form/let-body-form/let-reloop-form > implementations such that this protocol is implementable in the generic > binding library. The protocol I have in mind is that clauses with pattern (id > ...) get collected into one let-values, whereas adjacent forms defined in a > generic-binding way can choose to either be cascaded in a chosen form, or > collected into a chosen form. Additionally, since we want the ability to say > that non-matching isn't a failure, but a signal to continue, there is more we > need to be able to do with the for forms; indeed, the above template lies a > bit, since it does not mention the possibilities of #:when, #:unless, #:break > or #:final, where the first! t! > wo actually call loop with all the same accumulators, but with the sequence > "stepped forward one." This changes the format of the let-X-form setup, since > you would instead have a successful branch and a failing branch (consider a > match fall-through clause either raising an error or calling the loop on the > same accumulators with the stepped sequence(s)). > > This kind of overhaul is not something we can do externally to one of the > most used, non-trivial collection of macros in the Racket code base. We also > have to use a more conservative language to implement it, since it's so low > on the language tower. Perhaps later this year I'll have time to submit a > pull-request that opens the for macros up a bit more in this fashion, but I > anticipate a heavy push-back from core developers due to its supreme > importance to Racket's foundation. > > -Ian > > ----- Original Message ----- > From: "Asumu Takikawa" <as...@ccs.neu.edu> > To: "Konrad Hinsen" <konrad.hin...@fastmail.net> > Cc: users@racket-lang.org > Sent: Tuesday, September 3, 2013 9:12:54 AM GMT -05:00 US/Canada Eastern > Subject: Re: [racket] Combining iteration and match > > On 2013-09-03 11:32:23 +0200, Konrad Hinsen wrote: >> (for/list ([(list a b) some-sequence]) >> a) > > I usually use `match-define`: > > (for/list ([a+b some-sequence]) > (match-define (list a b) a+b) > a) > > Can be slightly longer than just `match` for simple cases, but doesn't > cause rightward drift. > > Cheers, > Asumu > ____________________ > Racket Users list: > http://lists.racket-lang.org/users > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users ____________________ Racket Users list: http://lists.racket-lang.org/users