[racket-dev] collects descriptions

2010-08-22 Thread Jon Rafkind
 Can someone provide me a somewhat brief description of what the 
following directories in the collects/ tree contain?


 * scribble
 * scribblings
 * scriblib

I have a vague impression but I don't understand the whole picture.. I 
think someone (Matthias?) requested a README file for each collect 
directory, I could put the information provided in such a file for each 
of these directories.

_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev


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

2010-08-22 Thread Will M. Farr
Noel,

Thanks for sharing your code, and for the comments.  Let me see if I understand 
this correctly: the following code should produce a total, a vector whose 
elements are the partial sums of elements at lower indices than the 
corresponding element of the input vector, and a vector whose elements are 
partial sums of elements at the index and lower indices of the input vector, 
right?

(define (total-and-partial-sums v)
  (for/fold/vector ((sum 0))
((i (vector-length v) 2) ;; Index, length, and two result vectors
 (x (in-vector v)))
(let ((sum-including-x (+ sum x)))
  (values sum-including-x sum sum-including-x ; The last two values are 
stored in the result vectors, first goes back in the fold

(total-and-partial-sums '#(1 2 3 4))
; => (values 10 (vector 0 1 3 6) (vector 1 3 6 10))

I can see how that would be very useful.  I see that you define for/vector 
using for/fold/vector, so the final body form of for/vector can produce 
multiple vectors, if the final expression in the body ... produces multiple 
values.  Also, you require naming the index, no?  So, the major differences are:

1. In my forms, the length is optional, and distinguished (when provided) from 
the for-clauses by a keyword argument.  In yours, it must be provided as the 
first for-clause (thus requiring that the index be named).

2. In my forms, the final body expression must produce exactly one value, which 
becomes the vector element.  In yours, the final body expression must produce 
exactly as many values as the third argument to the length clause (if provided) 
or 1 (if no third argument is present).  

As for difference 1, I think it's nice to be able to avoid providing a length 
if I don't want to.  Sometimes I may not really care about the efficiency of 
the loop, but will later need a vector, in which case it's a lot less effort to 
use (for/vector ((i (in-range 3))) ...) than to have to provide a length.  I 
also prefer the "distinguished" #:length keyword instead of shoehorning the 
length argument into a not-really-for-clause.  I'm curious what others think, 
however.

Difference #2 seems more significant to me.  I really like the idea of being 
able to produce multiple vectors simultaneously---as you say, it can have 
efficiency benefits and also be really convenient.  However, note that the 
for/list form does not allow multiple values from the last body expression, so 
there is an argument from consistency to prohibit it in for/vector as well.  
I'd be open to adding another keyword argument, however, to designate some 
number of vectors (independently of the presence or absence of the #:length 
keyword) for the output.  I'll put that in the next version, and we can see 
what other people think.  As with the #:length argument, I would prefer this to 
be a separate keyword---maybe #:num-vecs, maybe something else---rather than 
trying to fit it into a special for-clause.

Will


On Aug 22, 2010, at 4:11 PM, Noel Welsh wrote:

> On Sun, Aug 22, 2010 at 9:36 PM, Will M. Farr  wrote:
>> Matthew & co,
> ...
>> 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'm pretty sure this will exclude a lot of my code. I'll have to check 
> tomorrow.
> 
> My for/vector allows one to construct multiple vectors in one
> iteration. This is fairly useful to efficient code. I also bind the
> length to a name. I thought I checked that this counter was exactly
> the length after the comprehension terminated, but it appears I don't.
> Code is below.
> 
> You won't be surprised to hear I prefer my variant ;-).  I have uses
> for every feature that I can dreg up if anyone is interested. I'm keen
> to see a for/vector comprehension in Racket.
> 
> N.
> 
>  (define-syntax (for/fold/vector stx)
>(syntax-case stx ()
>  [(for/fold/vector
>([accum-id init-expr] ...)
>([idx length] for-clause ...)
>body ...)
>   (syntax
>(for/fold/vector
> ([accum-id init-expr] ...)
> ([idx length 1] for-clause ...)
> body ...))]
> 
>  [(for/fold/vector
>([accum-id init-expr] ...)
>([idx length n-vectors])
>body ...)
>   (syntax
>(let ([l length])
>  (for/fold/vector
>   ([accum-id init-expr] ...)
>   ([idx l n-vectors] [_ (in-range l)])
>   body ...)))]
> 
>  [(for/fold/vector
>()
>([idx length n-vectors] for-clause0 for-clause ...)
>body ...)
>   (with-syntax ([(v-id ...)
>  (datum->syntax
>   stx
>   (for/list ([i (in-range (syntax->datum (syntax
> n-vectors)))])
> (gensym 'for-vector))
>   (syntax n-vectors))]
> [(temp-

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

2010-08-22 Thread Will M. Farr
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
_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


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

2010-08-22 Thread Noel Welsh
On Sun, Aug 22, 2010 at 9:36 PM, Will M. Farr  wrote:
> Matthew & co,
...
> 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'm pretty sure this will exclude a lot of my code. I'll have to check tomorrow.

My for/vector allows one to construct multiple vectors in one
iteration. This is fairly useful to efficient code. I also bind the
length to a name. I thought I checked that this counter was exactly
the length after the comprehension terminated, but it appears I don't.
 Code is below.

You won't be surprised to hear I prefer my variant ;-).  I have uses
for every feature that I can dreg up if anyone is interested. I'm keen
to see a for/vector comprehension in Racket.

N.

  (define-syntax (for/fold/vector stx)
(syntax-case stx ()
  [(for/fold/vector
([accum-id init-expr] ...)
([idx length] for-clause ...)
body ...)
   (syntax
(for/fold/vector
 ([accum-id init-expr] ...)
 ([idx length 1] for-clause ...)
 body ...))]

  [(for/fold/vector
([accum-id init-expr] ...)
([idx length n-vectors])
body ...)
   (syntax
(let ([l length])
  (for/fold/vector
   ([accum-id init-expr] ...)
   ([idx l n-vectors] [_ (in-range l)])
   body ...)))]

  [(for/fold/vector
()
([idx length n-vectors] for-clause0 for-clause ...)
body ...)
   (with-syntax ([(v-id ...)
  (datum->syntax
   stx
   (for/list ([i (in-range (syntax->datum (syntax
n-vectors)))])
 (gensym 'for-vector))
   (syntax n-vectors))]
 [(temp-id ...)
  (datum->syntax
   stx
   (for/list ([i (in-range (syntax->datum (syntax
n-vectors)))])
 (gensym 'for-vector))
   (syntax n-vectors))])
 (syntax
  (let* ([l length]
 [idx 0]
 [v-id (make-vector l)] ...)
(begin
  (for (for-clause0 for-clause ...)
   (let-values (([temp-id ...] (let () body ...)))
 (vector-set! v-id idx temp-id) ...
 (set! idx (add1 idx
  (values v-id ...)]

  [(for/fold/vector
([accum-id0 init-expr0] [accum-id init-expr] ...)
([idx length n-vectors] for-clause0 for-clause ...)
body ...)
   (with-syntax ([(v-id ...)
  (datum->syntax
   stx
   (for/list ([i (in-range (syntax->datum (syntax
n-vectors)))])
 (gensym 'for-vector))
   (syntax n-vectors))]
 [(temp-id ...)
  (datum->syntax
   stx
   (for/list ([i (in-range (syntax->datum (syntax
n-vectors)))])
 (gensym 'for-vector))
   (syntax n-vectors))])
 (syntax
  (let* ([l length]
 [idx 0]
 [v-id (make-vector l)] ...)
(let-values (([accum-id0 accum-id ...]
  (for/fold ([accum-id0 init-expr0]
 [accum-id  init-expr] ...)
  (for-clause0 for-clause ...)
(let-values (([accum-id0 accum-id ... temp-id ...]
  (let () body ...)))
  (vector-set! v-id idx temp-id) ...
  (set! idx (add1 idx))
  (values accum-id0 accum-id ...)
  (values accum-id0 accum-id ... v-id ...)]))

  (define-syntax (for/vector stx)
(syntax-case stx ()
  [(for/vector (for-clause ...)
   body ...)
   (syntax (for/fold/vector () (for-clause ...) body ...))]))
_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev