On Mon, Aug 23, 2010 at 12:31 AM, Neil Toronto <[email protected]> wrote:
> This email is feedback on using Typed Racket to develop a new library (i.e. > it isn't originally untyped code) that's about 3500 lines long, and some > questions. Thanks for the feedback! > Some macros with names starting with "forall" provide syntactic sugar for > mapping over arrays simultaneously. Here's an example of use: > > (foralln/flvectorn: > ([x : Float (<-flvectorn xs)] > [y : Float (<-flvectorn ys)]) > (for/fold: : Float ([dm : Float 0.0]) ([pt : vec2 (in-list pts)]) > (+ dm (delta-mass-from pt (vec2 x y)))))) > > Here, "flvectorn" is an N-dimensional flvector, and "<-flvectorn" is special > syntax like "in-list" (i.e. forall recognizes it as creating an array backed > by an flvectorn and inlines unsafe-flvectorn-ref accordingly). Is this the same as the (brand-new) `for/flvector' and `in-flvector'? > - Why require "return" or body types for for/*: loops in TR? I haven't > needed them in forall/*: loops. Also, writing the "Listof" in "for/list: : > (Listof T)" is annoying. I know it's a list from reading "for/list:", and > for/list: knows it, too. I also know the return type of a "for/fold:" from > the accumulators' types; why require them twice? I'm also annoyed by having > to give a body type for every named "let:". > > Similarly, why require return types for functions defined with "define:"? > I'd almost rather write lambdas than give another annotation. (Not that I > use define: very much.) In general, `define:' and `let:' require return types since they define (potentially) recursive functions, and therefore a type needs to be given to the function, which wouldn't be known without typechecking the body, which could reference the function. This is also why `for/list:' needs a return type annotation - it's expanding into a `let loop' underneath. > - Related: can we get a runtime cast/refine macro? Occurrence typing makes > a naive one easy to implement: (let ([x <expr>]) (if (pred? x) x (error > ...))). Easy implementation means everyone will duplicate it; might as well > incorporate a good one. See `assert' in the docs. > - Polymorphic structs being proper subtypes of their parent structs would > be really nice. As it is, I can't figure out how to cleanly have a > "(vector-array T)" subtype of "(array T)" that gives private array functions > access to the vector backing an array. If I had that, I could collapse > compositions of certain array ops at runtime and remove some duplicate > bounds checks. I'm not sure exactly what you mean here. Can you give an example? > - Futures don't work with TR. I had to use require/typed to get them, so I > gather that they're not officially supported. From what I can tell, for TR > code, the JIT gives a large max_let_depth to even simple thunks like (lambda > () 1). It's a shame, because splitting up forall loops with bodies that use > nothing but float ops seems like a killer app for futures. I'll add type annotations for `future' and `touch'. (lambda () 1) should be the same in TR as in regular Racket, so I'm surprised the JIT sees them differently. > - Pie-in-the-sky: notice that "<-flvectorn" above is really just a type > annotation that the forall macro understands. It would be nice if > compositional macros could get the types of their arguments - I could have > forall map over any array-like thing without requiring a declaration of what > it is. > > I understand why this is hard: the inferred types depend on expansion, and > the expansion would depend on types. While tricky, it seems that finding a > fixpoint w.r.t. the subtype relation could work. Most macros would iterate > zero times or once. Expanding to expressions with uncomparable types would > be an error. > > Typeclasses allow function dispatch on the types of arguments; this would > allow a sort of macro dispatch on the types of expanded inner syntax. You > could probably define typeclasses in terms of it. > > Don't attack it too fiercely, though, as I haven't given it much deep > thought. :) Also, it is a pie... in the sky. Yes, other people have wanted this as well. It isn't at all obvious how to do this in TR current architecture, but I'll keep thinking. For the particular `<-flvector' case, right now the optimizer makes this: (for ([i some-vector]) ...) just as fast as this: (for ([i (in-vector some-vector)]) ...) so perhaps the same can be done for `in-flvector' and other such operations. Thanks again for the feedback. -- sam th [email protected] _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users

