[racket-dev] Wrapping loops for TR isn't working, and the type annotations are for the wrong value
On 08/15/2012 05:24 AM, Sam Tobin-Hochstadt wrote:
> On Tue, Aug 14, 2012 at 11:52 PM, Neil Toronto <neil.toronto at gmail.com> wrote:
>>
>> Some typed "for" loops would have to be reimplemented, unless inference
>> improves a lot. To make this easier, I've attached an example implementation
>> of `for/vector:' and `for*/vector:'. It allows both body and result
>> annotations, handles #:length properly, allows #:when clauses anywhere, and
>> fixes the two bugs in `for/vector' I reported today.
>
> Thanks for doing this. I worry a little about re-implementing
> `for/vector`, since now we have two implementations to keep in sync.
> Eventually, I think Typed Racket needs to support more agressive
> inference than it currently does; that's the reality of dealing with a
> macro-generated language. But for the moment, this would make things
> better for people.
Agree on all counts.
BTW, what do you think of deprecating result annotations and using body
annotations instead?
> Two questions: (1) how similar is the generated code to the expansion
> of plain `for/vector`[?]...
In the case where #:length is missing, not very. I couldn't use
`for/list:' and convert to a vector because I couldn't reliably generate
(Listof T) from the result type (because of type aliases). On the plus
side, mine's about twice as fast. It expands to plain `for:' and bangs
values into a growable vector.
When #:length is given, it's similar in that it creates a vector outside
the loop and bangs values into it. But I have to start with (define vs
(vector)) and then (set! vs (make-vector n v)) when the first value `v'
is computed. The docs for `for/vector' say any values not computed in
the loop are supposed to be 0, but that doesn't work well in TR: it'd
have to create a (Vectorof (U T 0)). Ick.
I wouldn't mind if `for/vector' behaved the same way, since the current
behavior makes it easy to violate contracts. On my computer, my
`for/vector:' with #:length takes only 5% longer to run than an
equivalent `for/vector' loop with moderate-sized vectors.
> and (2) would it be possible to abstract the implementation of
> Racket's `for/vector` to allow you to re-use some of that code here?
I wouldn't want to because `for/vector' is currently broken when
#:length is given. (See PR 13029 and PR 13030.)
I think the only way to fix it is to implement it like I did: expand to
plain `for:' and mutate an external index. So it might be better to have
them share a new common implementation.
I think I could work one up that expands to code with annotations when
used from TR and to code without annotations otherwise. I'd use the
"maybe-annotate" macro (`ann:') for every annotation, not just for
annotating with the optional result and body types.
Neil ⊥