Re: [racket-users] Idiomatic way to include numbers in a map?
That's very cool. Thank you, Matthew. On Fri, Mar 3, 2017 at 6:50 PM, Matthew Butterickwrote: > > On Mar 2, 2017, at 9:17 AM, David Storrs wrote: > > I could, it's just extremely more verbose and therefore obfuscates what's > actually going on as compared to the 'map' form. > > > Why not turn it into a macro that preserves your preferred notation: > > > #lang racket > (struct foo (a b c) #:transparent) > (define lst-A '(a b)) > (define lst-B '(d e)) > > (require (for-syntax syntax/parse)) > (define-syntax (map-index stx) > (syntax-parse stx > #:datum-literals (current-index) > [(_ proc xs ... current-index ys ...) > (with-syntax ([(x-it ...) (generate-temporaries #'(xs ...))] >[(y-it ...) (generate-temporaries #'(ys ...))]) >#'(for/list ([x-it (in-list xs)] ... [y-it (in-list ys)] ... > [index (in-naturals)]) >(proc x-it ... index y-it ...)))])) > > (map-index > foo > lst-A > lst-B > current-index) ; ; (list (foo 'a 'd 0) (foo 'b 'e 1)) > > (map-index > foo > current-index > lst-A > lst-B) ; (list (foo 0 'a 'd) (foo 1 'b 'e)) > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Idiomatic way to include numbers in a map?
> On Mar 2, 2017, at 9:17 AM, David Storrswrote: > > I could, it's just extremely more verbose and therefore obfuscates what's > actually going on as compared to the 'map' form. Why not turn it into a macro that preserves your preferred notation: #lang racket (struct foo (a b c) #:transparent) (define lst-A '(a b)) (define lst-B '(d e)) (require (for-syntax syntax/parse)) (define-syntax (map-index stx) (syntax-parse stx #:datum-literals (current-index) [(_ proc xs ... current-index ys ...) (with-syntax ([(x-it ...) (generate-temporaries #'(xs ...))] [(y-it ...) (generate-temporaries #'(ys ...))]) #'(for/list ([x-it (in-list xs)] ... [y-it (in-list ys)] ... [index (in-naturals)]) (proc x-it ... index y-it ...)))])) (map-index foo lst-A lst-B current-index) ; ; (list (foo 'a 'd 0) (foo 'b 'e 1)) (map-index foo current-index lst-A lst-B) ; (list (foo 0 'a 'd) (foo 1 'b 'e)) -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Idiomatic way to include numbers in a map?
There is a "generic" `sequence-map`. But it's not variadic like `map` -- and like you want in your example. You could try writing a variadic `sequence-map`? As for `for/list`, you _could_ write: (for/list ([a as] [b bs] [n (in-naturals)]) (foo a b n)) It's faster if you supply `in-list` for `as` and `bs`, as did David. When you do, it expands to code that's about as fast as if you wrote it by hand. But if you know the list will have only a few items, and it doesn't matter, you could omit `in-list`. Granted it's still more verbose than `map` style. Speaking of writing by hand, you could use `match*` to remove some car/cdr textbook tedium -- but it's still fairly tedious: (let loop ([as as] [bs bs] [n 1]) ;`in-naturals` is 1.. -- use 0 here if you prefer (match* [as bs] [[(cons a as) (cons b bs)] (cons (foo a b n) (loop as bs (add1 n)))] [[_ _] '()])) I think one theme here is a trade-off between abstraction and speed Another is a trade-off between functions and macros. Macros like `for` and `match` can expand into efficient code that you wouldn't want to write by hand. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Idiomatic way to include numbers in a map?
On Thu, Mar 2, 2017 at 12:15 PM, David Storrswrote: > > > > On Thu, Mar 2, 2017 at 11:22 AM, David Christiansen < > da...@davidchristiansen.dk> wrote: > >> > Not with map, which requires equal-length arguments. >> > >> > You could do the slightly less ugly: >> > >> > (map >> > foo >> > lst-A >> > lst-B >> > (range (length lst-A))) >> >> Why not do it this way? >> >> (struct foo (a b c)) >> (define lst-A '(a b)) >> (define lst-B '(d e)) >> (for/list ([a (in-list lst-A)] >>[b (in-list lst-B)] >>[n (in-naturals)]) >> (foo a b n)) >> >> This seems to be the nicest of the lot. >> >> /David > > > I could, it's just extremely more verbose and therefore obfuscates what's > actually going on as compared to the 'map' form. > > The issue with streams and sequences not being iterable in some cases has > tripped me up several times. I confess I don't understand the design > decisions behind them. Can someone ELI5 for me about what exactly they are > and why they work the way they do / aren't interchangeable? From a naive > perspective it seems like it would be possible to make them work smoothly > together by adding a "cond: choose the right iterator func based on the > type" under the hood. Something like the following, except this is > probably very slow and I'd need to figure out the appropriate generation > for the '(choose-iter sourceN)' lines: > > (define-syntax relaxed-map > > (syntax-case stx () > [(_ func source1 source2 ...) > (let () >(define (choose-iter x) > (cond [(list? x) (list list-ref x)] >[(stream? x) (list stream-ref x)] >[(sequence? x) (list sequence-ref x)])) >(for/list ((i (in-range (add1 (min (map length source1 source2 > ...)) > (list ((choose-iter source1) source1 i) >((choose-iter source2) source2 i) >...)))])) ;; This won't actually generate the 'choose-iter' > lines properly > > Also, that needs to be '(apply min (map ...' Still, you get the point. >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Racket Users" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to racket-users+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> > > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Idiomatic way to include numbers in a map?
On Thu, Mar 2, 2017 at 11:22 AM, David Christiansen < da...@davidchristiansen.dk> wrote: > > Not with map, which requires equal-length arguments. > > > > You could do the slightly less ugly: > > > > (map > > foo > > lst-A > > lst-B > > (range (length lst-A))) > > Why not do it this way? > > (struct foo (a b c)) > (define lst-A '(a b)) > (define lst-B '(d e)) > (for/list ([a (in-list lst-A)] >[b (in-list lst-B)] >[n (in-naturals)]) > (foo a b n)) > > This seems to be the nicest of the lot. > > /David I could, it's just extremely more verbose and therefore obfuscates what's actually going on as compared to the 'map' form. The issue with streams and sequences not being iterable in some cases has tripped me up several times. I confess I don't understand the design decisions behind them. Can someone ELI5 for me about what exactly they are and why they work the way they do / aren't interchangeable? From a naive perspective it seems like it would be possible to make them work smoothly together by adding a "cond: choose the right iterator func based on the type" under the hood. Something like the following, except this is probably very slow and I'd need to figure out the appropriate generation for the '(choose-iter sourceN)' lines: (define-syntax relaxed-map (syntax-case stx () [(_ func source1 source2 ...) (let () (define (choose-iter x) (cond [(list? x) (list list-ref x)] [(stream? x) (list stream-ref x)] [(sequence? x) (list sequence-ref x)])) (for/list ((i (in-range (add1 (min (map length source1 source2 ...)) (list ((choose-iter source1) source1 i) ((choose-iter source2) source2 i) ...)))])) ;; This won't actually generate the 'choose-iter' lines properly > > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Idiomatic way to include numbers in a map?
> Not with map, which requires equal-length arguments. > > You could do the slightly less ugly: > > (map > foo > lst-A > lst-B > (range (length lst-A))) Why not do it this way? (struct foo (a b c)) (define lst-A '(a b)) (define lst-B '(d e)) (for/list ([a (in-list lst-A)] [b (in-list lst-B)] [n (in-naturals)]) (foo a b n)) This seems to be the nicest of the lot. /David -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Idiomatic way to include numbers in a map?
Not with map, which requires equal-length arguments. You could do the slightly less ugly: (map foo lst-A lst-B (range (length lst-A))) On Thu, Mar 2, 2017 at 11:14 AM, David Storrswrote: > > > On Thu, Mar 2, 2017 at 10:09 AM, Stephen Chang wrote: >> >> The in-X forms are sequences, and must be used with the sequence API, ie >> for/X. >> >> map only works with lists, so you could use build-list or range: >> (map >> foo >> lst-A >> lst-B >> (range 2)) >> > Is there a way to do it if I don't know how many items will be in the list? > What I want is to say "just keep sticking numbers in until one of the lists > runs out." I could say (range 1) but that's ugly. > > >> >> On Thu, Mar 2, 2017 at 9:55 AM, David Storrs >> wrote: >> > I'd like to be able to do something like this: >> > >> > (struct foo (a b c)) >> > (define lst-A '(a b)) >> > (define lst-B '(d e)) >> > (map >> > foo >> > lst-A >> > lst-B >> > (in-naturals)) >> > >> > I'd expected this to produce: (foo 'a 'd 0) (foo 'b 'e 1), but instead >> > it >> > throws an exception "expected list, given stream". I could do it with a >> > for/list but that's much more verbose. What would be the idiomatic way >> > of >> > doing this? >> > >> > -- >> > You received this message because you are subscribed to the Google >> > Groups >> > "Racket Users" group. >> > To unsubscribe from this group and stop receiving emails from it, send >> > an >> > email to racket-users+unsubscr...@googlegroups.com. >> > For more options, visit https://groups.google.com/d/optout. > > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Idiomatic way to include numbers in a map?
On Thu, Mar 2, 2017 at 10:09 AM, Stephen Changwrote: > The in-X forms are sequences, and must be used with the sequence API, ie > for/X. > > map only works with lists, so you could use build-list or range: > (map > foo > lst-A > lst-B > (range 2)) > > Is there a way to do it if I don't know how many items will be in the list? What I want is to say "just keep sticking numbers in until one of the lists runs out." I could say (range 1) but that's ugly. > On Thu, Mar 2, 2017 at 9:55 AM, David Storrs > wrote: > > I'd like to be able to do something like this: > > > > (struct foo (a b c)) > > (define lst-A '(a b)) > > (define lst-B '(d e)) > > (map > > foo > > lst-A > > lst-B > > (in-naturals)) > > > > I'd expected this to produce: (foo 'a 'd 0) (foo 'b 'e 1), but instead > it > > throws an exception "expected list, given stream". I could do it with a > > for/list but that's much more verbose. What would be the idiomatic way > of > > doing this? > > > > -- > > You received this message because you are subscribed to the Google Groups > > "Racket Users" group. > > To unsubscribe from this group and stop receiving emails from it, send an > > email to racket-users+unsubscr...@googlegroups.com. > > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Idiomatic way to include numbers in a map?
The in-X forms are sequences, and must be used with the sequence API, ie for/X. map only works with lists, so you could use build-list or range: (map foo lst-A lst-B (range 2)) On Thu, Mar 2, 2017 at 9:55 AM, David Storrswrote: > I'd like to be able to do something like this: > > (struct foo (a b c)) > (define lst-A '(a b)) > (define lst-B '(d e)) > (map > foo > lst-A > lst-B > (in-naturals)) > > I'd expected this to produce: (foo 'a 'd 0) (foo 'b 'e 1), but instead it > throws an exception "expected list, given stream". I could do it with a > for/list but that's much more verbose. What would be the idiomatic way of > doing this? > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[racket-users] Idiomatic way to include numbers in a map?
I'd like to be able to do something like this: (struct foo (a b c)) (define lst-A '(a b)) (define lst-B '(d e)) (map foo lst-A lst-B (in-naturals)) I'd expected this to produce: (foo 'a 'd 0) (foo 'b 'e 1), but instead it throws an exception "expected list, given stream". I could do it with a for/list but that's much more verbose. What would be the idiomatic way of doing this? -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.