spdegabrielle
2020-6-9 18:03:33

Asked on discord: “How do i print list of lists as a matrix, instead of these really long lines?”


samth
2020-6-9 18:03:57

pretty-print


anything
2020-6-9 19:03:31

I have a procedure that produces a list of lists — one per each call, like a generator. How can I collect all these values into a list? I thought a for/list would do, but I end up iterating each value in the first list produced. (I don’t want to look inside the item produced at the iteration. I want to treat it as a whole.)

racket@api.rkt> (define port (make-port-test)) racket@api.rkt> port #<input-port:string> racket@api.rkt> ((make-payout-reader port)) '("amount" "note" "email" "id")

Here’s my attempt:

(define (make-items port) (for/list ([item ((make-payout-reader port))]) item))

Here’s the result:

racket@api.rkt> (make-items (make-port-test)) '("amount" "note" "email" "id")

I thought item would be the entire list of values, but it ends up being “amount”, “note”, “email”, “id”, in this order.


soegaard2
2020-6-9 19:07:11

So the port contains more lines?


samth
2020-6-9 19:08:25

@anything I’m confused about something here. If your procedure produces a list of values, it is a list already, so you don’t need to do anything.


anything
2020-6-9 19:11:39

@soegaard2 Yes, it contains more lines. I’m reading a CSV file with reading-csv.


anything
2020-6-9 19:11:56

Sorry my description was terrible. I think I fixed it now.


anything
2020-6-9 19:12:57

I think I just want to cons each list into an accumulator-list.


anything
2020-6-9 19:13:11

What’s the idiomatic way to do this?


anything
2020-6-9 19:15:51

Here’s what I want.

(define (make-items port) (define row ((make-payout-reader port))) (cond [(null? row) '()] [else (cons row (make-items port))]))

racket@api.rkt> (make-items (make-port-test)) '(("amount" "note" "email" "id") ("1.01" "Thank you!" "user-1" "") ("1.02" "Thanks!" "user-2" "cx123abc"))

What’s the idiomatic way to do this?


soegaard2
2020-6-9 19:19:00

I would make a loop. If the “end object” is reached the empty list is returned. Otherwise the current values is consed onto the result of reading the rest. #lang racket (require csv-reading) (define next-row (make-csv-reader (open-input-string "1,2\n3,4\n") '((separator-chars #\,) (strip-leading-whitespace? . #t) (strip-trailing-whitespace? . #t)))) (define (all-rows) (match (next-row) ['() '()] [row (cons row (all-rows))]))


soegaard2
2020-6-9 19:20:07

I think csv-reading uses ’() when the end is reached - so the end object is ’().


soegaard2
2020-6-9 19:20:38

But … if an empty line also produces ’() then you only get the lines before the empty line.


soegaard2
2020-6-9 19:21:03

So in this particular case, I would probably use csv->list.


anything
2020-6-9 19:21:43

It does — ’(). I see you guys use match a lot. Interesting code. Thanks! (Yes, my code would have the same problem…) (Good catch.)


soegaard2
2020-6-9 19:22:48

That’s just habit. Your make-items is just as fine.


anything
2020-6-9 19:27:19

New question. Say I have a procedure called make-payee such that (make-payee v1 v2 v3 v4) produces a payee-structure. I have a list '(v1 v2 v3 v4). How can I make the call (make-payee ,@my-list) work? It seems I need a quasiquote to splice? I don’t know how to do that.


soegaard2
2020-6-9 19:27:58

(apply make-payee the-list)


anything
2020-6-9 19:28:26

Aha! Beautiful. Thank you!


sorawee
2020-6-9 21:36:18

Well, not quite. For small matrices, they will still be on one line. For really large matrices, each cell will be on its own line.


sorawee
2020-6-9 21:37:01

I know @samth knows this already, but just put this here in case other people find this information useful.


sorawee
2020-6-9 21:38:08

So if you want the matrix format, just write your own. It’s a good programming exercise


badkins
2020-6-9 23:21:47

I’m probably atypical, but I like the more Scheme like “named let” for looping: (define lists '((1 2 3) (4 5 6) (7 8 9))) (let loop ([ lists lists ][ result '() ]) (if (null? lists) (reverse result) (loop (cdr lists) (cons (car lists) result))))