ben.knoble
2021-9-25 11:37:03

Im not as familiar with the sequence or stream apis, but why the trip through streams and stream first?


ben.knoble
2021-9-25 13:43:15

(The answer to my question is because of how in-slice works; but I found two other ways to do it. If you put in-cycle at the top of the threading like you did originally, my first option is slightly shorter because it doesn’t need stream-first.) (~> '(A B) in-cycle sequence->stream (stream-take 9) sequence->list) ;;=> '(A B A B A B A B A) or (for/list ([ab (in-cycle '(A B))] [n (in-naturals)]) #:break (>= n 9) ab) ;;=> '(A B A B A B A B A)


samth
2021-9-25 18:03:12

You could even use (in-range 9) there


gmauer
2021-9-25 20:14:04

I needed the first one though. I got this working (~> (in-cycle '(A B)) (in-slice 9 _) (sequence-ref _ 0)) really surprising I couldn’t find a sequence-take (even though sequence-tail exists) nor a sequence-first . I think that’s the reason I assumed data/collection was a popular go-to since it makes all that stuff “just work”, but since it conflicts with typed/racket, I just won’t use it and stick to the sequence and stream stuff


gmauer
2021-9-26 00:39:07

Next question - what is the equivalent of a zip function which can combine multiple sequences? Specifically, map doesn’t work if the input sequences are not of equal length, and I don’t want to make an intermediate list


sorawee
2021-9-26 00:41:18

zipShortest can be done roughly by using for forms


gmauer
2021-9-26 00:47:14

huh.. ok I was looking at those docs now but I don’t see how? do you provide multiple for-clauses?


sorawee
2021-9-26 00:48:41

Yes:

(for/list ([x '(1 2 3)] [y '(1 2 3 4)]) (list x y)) ;=> '((1 1) (2 2) (3 3))


gmauer
2021-9-26 00:51:56

oh, interesting, so it does shortest already, cool


gmauer
2021-9-26 01:58:36

hmm…so actually trying to write zip-shortest I can’t quite figure it out. The function I want would be varadic same as map so you can do things like (zip-shortest list lst1 lst2 lst3 lst4) and you’d get back a list of lists each with 4 items in it.

I can write it with the for form, but no clue how I would do it when the number of for-clause s might vary depending on input



sorawee
2021-9-26 02:00:51

Actually… you asked that question :smile:


gmauer
2021-9-26 02:15:35

oooh…yeah would you look at that. Yea, I’ve been coming back to Racket to play with it every few months for 2 years now huh?


gmauer
2021-9-26 02:17:27

what would be the technique if I wanted to write that as a macro? would I have to dynamically generate variable names or is there a helper for that?


sorawee
2021-9-26 02:19:36

So, just want to make sure you understand the limitation of macros. You can definitely write zip-shortest as a macro, but it means you can’t do:

(apply zip-shortest (list a b c)) any more (well, you actually can, but it essentially falls back to the solution in StackOverflow). Is this what you really want?


sorawee
2021-9-26 02:20:16

Dynamically generate n variable names can be done by using a function named generate-temporaries.


gmauer
2021-9-26 02:20:46

Yeah, just for learning’s sake. I get that it’s not a spectacular way to do stuff


gmauer
2021-9-26 02:22:05

Though if I understand it correctly, if it was a macro then it could theoretically be pulled into another typed/racket package and still work even without me providing any annotations, right? Since by the time the type checker runs it will have been expanded?


sorawee
2021-9-26 02:23:48

@samth would be able to answer that better than me, but my impression is that this is incorrect: macro usually complicates type checking.


sorawee
2021-9-26 02:24:04

FYI, here’s what the macro would look like:

#lang racket (require syntax/parse/define) (define-syntax-parse-rule (zip-shortest xs ...) #:with (x ...) (generate-temporaries (attribute xs)) (for/list ([x (in-list xs)] ...) (list x ...))) (zip-shortest (list 1 2 3) (list 1 2 3 4) (list 1 2 3 4 5))


gmauer
2021-9-26 02:24:10

ooh cool, thanks