[racket-dev] [plt] Push #20898: master branch updated

From: Will M. Farr (wmfarr at gmail.com)
Date: Sun Aug 22 16:36:03 EDT 2010

Matthew & co,

On Aug 21, 2010, at 7:14 AM, Matthew Flatt wrote:

> I didn't think of this before, but probably you should add a check that
> the length expression proceduces a nonnegative exact integer:
> 
>         (syntax/loc stx
>           (let ((len length-expr))
>             (unless (exact-nonnegative-integer? len)
>               (raise-type-error 'for/vector "exact nonnegative integer" len))
>             (let ((v (make-vector len)))
>               (for ((i (in-naturals))
>                     for-clause ...)
>                 (vector-set! v i body))
>               v)))

Absolutely.  I'll take care of it.  

> More things that I didn't think of below...
> 
>> As for the issue 
>> of a #:size that doesn't match the length of the iteration, I have been 
>> thinking about adding a check inside the loop (for sizes that are too small), 
>> and a check outside the loop (for sizes that are too large).  If the size does 
>> not match the number of loop iterations would it be better to (error 
>> 'for/vector "loop iterations (~a) and vector size (~a) do not match" iter 
>> size), raise one of the exn:fail:contract type exceptions, or manually 
>> construct a blame object and (raise-blame-error ...), or ...?  If it were 
>> simply my code, I would just call (error ...), but that's maybe not the best 
>> in a general purpose library.
> 
> A `exn:fail:contract' exception would be the right one. It's probably
> easiest to use `raise-mismatch-error'.
> 
> It might also be ok to use
> 
>  (i (in-range 0 len))
> 
> and say that the loop stops when either the sequence runs out or the
> number of iterations matches the length. I'd be happy with that but i
> can imagine that others might prefer an error.

I think I prefer this second approach; maybe there is sometimes a use for creating a vector that is longer than its initially set length.  For example, I could imagine having an extendable vector implementation where you want to leave some space at the end for future expansion.

> Either choice --- error or stopping --- interacts awkwardly with
> `for*/vector'. If you've going to raise an exception, the natural thing
> to do with `for/vector' would be to stop as soon as the sequence goes
> too far. But `for*/vector' with a length currently just uses
> `for*/vector' without the length; you could check afterward, but that
> would be different than the natural choice for `for/vector'.
> 
> Along similar lines, every `for/vector' is a `for*/vector' in a way,
> because a `#:when' clause can introduce a nesting. The `for/vector'
> macro with an without a length behaves very differently than the one
> with a length when a `#:when' clause is used.
> 
> Maybe `for/vector' with a length clause should be syntactically
> restricted to have no `#:when' clauses, and maybe there just shouldn't
> be a variant of `for*/vector' that supports `#:length'.

I'll make sure to throw a syntax error if I see a #:when in the for-clauses, and I think I should give up on the for*/vector #:length variant.  I was hoping that you would have some sort of neat trick to keep a running counter during the nested iteration....

I'll send Sam the latest when I'm done with the modifications.

Will

Posted on the dev mailing list.