[plt-dev] problems with extending `for' syntax

From: Sam TH (samth at ccs.neu.edu)
Date: Sun Feb 22 19:18:14 EST 2009

On Sun, Feb 22, 2009 at 6:01 PM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> At Sun, 22 Feb 2009 17:44:42 -0500, Sam TH wrote:
>> I'd like to write a sequence syntax that uses `match'-style pattern
>> matching.  Unfortunately, this doesn't seem to be currently possible,
>> but it's close.
>> First, something like this is ruled straight out:
>> (for/list ([(? (lambda (x) #t) x) (:match (list 1 2 3))]) x)
>> since (lambda (x) #t) is not an identifier.  This is ruled out
>> *before* the `:match' expander is given control.
>> Second, it's not possible to distinguish between the client writing this:
>> (for/list ([x (:match e)]) ...)
>> and this:
>> (for/list ([(x) (:match e)]) ...)
>> which, while they have the same semantics for `in-list', would have
>> very different semantics for `:match'.
>> I think the easiest solution would be to (1) accept any pattern in the
>> binding position, and have individual sequence-syntax forms rule them
>> out (perhaps `define-sequence-syntax' could make this easy), and (2)
>> provide a lower-level form which is given the raw pattern, without any
>> transformation.
>> I'll write up a patch, provided anyone is interested.
> It sounds worth trying, but I'm not sure it will work easily.
> The existing `for' forms were designed with the idea that the
> right-hand side of a binding is always an expression. If the expression
> has a certain shape, then you might get better performance, but the
> shape of the expression doesn't affect the binding.
> A benefit of that design is that you can derive new `for'-like forms
> that wrap some right-hand sides with sequence converters. For example,
> a derived form might wrap a right-hand side with `stop-before'. If I
> remember correctly, then some of the `for' forms (perhaps `for/or' or
> `for/and') are implemented that way.
> In other words, the constraint that the right-hand side is always an
> expression might be built deep enough into the design that it's
> difficult to change. But I'm not sure.

Attached is my initial effort.  'for.diff' is a diff for
'scheme/private/for.ss', implementing `define-raw-sequence-syntax'.
Then 'test.ss' uses that to implement `:match' and `:match*', which
match single- and multiple-value generators, respectively.  I've tried
out a bunch of examples (included in the file), and they all seem to
work as intended, including the ones using `for/and' and `for/or'.

Do you think this is a reasonable strategy?  Is there something I've overlooked?

sam th
samth at ccs.neu.edu
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.ss
Type: application/octet-stream
Size: 2148 bytes
Desc: not available
URL: <http://lists.racket-lang.org/dev/archive/attachments/20090222/e620f91d/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: for.diff
Type: text/x-diff
Size: 4528 bytes
Desc: not available
URL: <http://lists.racket-lang.org/dev/archive/attachments/20090222/e620f91d/attachment.bin>

Posted on the dev mailing list.