[racket] Typed Racket and macros expanding to for*:

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Tue Jul 24 11:11:01 EDT 2012

This kills an infinite or a large-number-of-iterations loop that the programmer may have tried to specify with the for:-clauses. 


On Jul 24, 2012, at 11:07 AM, Vincent St-Amour wrote:

> You could capture the continuation outside `for*' check the index in the
> body and jump out when it gets out of range.
> 
>    (let/ec: done : Void
>      (for*: (for:-clause ...)
>        (unless (< i m*n) (done (void)))
>        (define x (let () . defs+exprs))
>        (vector-set! v i x)
>        (set! i (assert (+ i 1) index?))))
> 
> 
> Vincent
> 
> 
> At Tue, 24 Jul 2012 13:33:55 +0200,
> Jens Axel Søgaard wrote:
>> 
>> Hi All,
>> 
>> I am writing a comprehension for*/matrix: that collects
>> numbers and puts them in an mxn matrix.
>> 
>> A simple example:
>> 
>> (for*/matrix: : Number 2 3 ([i (in-range 6)]) i)
>> ; => '#(0 1 2
>> ;          3 4 5)
>> 
>> In this post the representation is simplified to a vector.
>> 
>> An example more:
>> 
>> (for*/matrix: : Number 2 3
>>  ([i (in-range 2)]
>>   [j (in-range 3)])
>>  (+ (* 10 i) j))
>> ; => '# (   0  1   2
>> ;           10 11 12)
>> 
>> The two examples above work fine with the code below.
>> 
>> However I'd like the comprehension to automatically when m*n
>> numbers have been generated. That is, I'd like
>> 
>>    (for*/matrix: : Number 2 3 ([i (in-naturals)]) i)
>> 
>> to produce #(0 1 2 3 4 5).
>> 
>> The current expansion generates an index out of range error in vector-set!.
>> In for/matrix I solved the problem by adding a dummy sequence
>> before the for:-clauses provided by the macro user.
>> 
>>         (for: ([dummy (in-range (* m n))] for:-clause ...)
>>           (define x (let () . defs+exprs))
>> 
>> This works because for: evaluates the sequences in parallel.
>> This also implies I can't use the same trick for for*: which
>> evaluates the sequences in a nested fashion.
>> 
>> The question is how to modify the expansion below
>> to  automatically stop after m*n elements have been
>> generated?
>> 
>> /Jens Axel
>> 
>> 
>> #lang typed/racket
>> 
>> (define-syntax (for*/matrix: stx)
>>  (syntax-case stx ()
>>    [(_ : type m-expr n-expr (for:-clause ...) . defs+exprs)
>>     (syntax/loc stx
>>       (let ()
>>         (define: m   : Index           m-expr)
>>         (define: n   : Index           n-expr)
>>         (define: m*n : Index           (assert (* m n) index?))
>>         (define: v   : (Vectorof type) (make-vector m*n 0))
>>         (define: i   : Index           0)
>>         (for*: (for:-clause ...)
>>           (define x (let () . defs+exprs))
>>           (vector-set! v i x)
>>           (set! i (assert (+ i 1) index?)))
>>         v))]))
>> 
>> (for*/matrix: : Number 2 3
>>  ([i (in-range 2)]
>>   [j (in-range 3)])
>>  (+ (* 10 i) j))
>> ; => '#(  0  1  2
>> ;        10 11 12)
>> 
>> (for*/matrix: : Number 2 3 ([i (in-range 6)]) i)
>> ; => '#(0 1 2
>> ;       3 4 5)
>> 
>> (for*/matrix: : Number 2 3 ([i (in-naturals)]) i)
>> ; vector-set!: index out of range
>> ____________________
>>  Racket Users list:
>>  http://lists.racket-lang.org/users
> 
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users



Posted on the users mailing list.