Re: [racket-users] Idiomatic way to include numbers in a map?

2017-03-03 Thread David Storrs
That's very cool.  Thank you, Matthew.

On Fri, Mar 3, 2017 at 6:50 PM, Matthew Butterick  wrote:

>
> 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?

2017-03-03 Thread Matthew Butterick

> 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.


Re: [racket-users] Idiomatic way to include numbers in a map?

2017-03-02 Thread Greg Hendershott
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?

2017-03-02 Thread David Storrs
On Thu, Mar 2, 2017 at 12:15 PM, David Storrs 
wrote:

>
>
>
> 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?

2017-03-02 Thread David Storrs
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?

2017-03-02 Thread David Christiansen

> 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?

2017-03-02 Thread Stephen Chang
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 Storrs  wrote:
>
>
> 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?

2017-03-02 Thread David Storrs
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.


Re: [racket-users] Idiomatic way to include numbers in a map?

2017-03-02 Thread Stephen Chang
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 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.


[racket-users] Idiomatic way to include numbers in a map?

2017-03-02 Thread David Storrs
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.