slack1
2018-5-2 11:22:42

If you want to do something to a list of list of X


slack1
2018-5-2 11:22:50

Is it idiomatic to just have 2 nested maps?


greg
2018-5-2 11:54:39

I think so. Nested maps, or, for/lists. Whichever you prefer. If map, you could use curry to make it even more terse if you prefer. #lang racket/base (require racket/function) (define xss '((1 2) (3 4) (5 6))) (map (curry map add1) xss) (for/list ([outer (in-list xss)]) (for/list ([inner (in-list outer)]) (add1 inner)))


greg
2018-5-2 11:58:37

Aside from https://docs.racket-lang.org/style/ I’m not sure Racket has a strong sense of “idiomatic”, compared to some other languages.


greg
2018-5-2 11:59:31

Maybe just common sense things like “local consistency”. e.g. In a project or a certain file, maybe pick one and generally stick with it.


greg
2018-5-2 12:00:05

Where “it” is some choice like define vs. let, map and friends vs. list comprehensions, and so on.


greg
2018-5-2 12:00:49

I think most Racketeers will be OK with the choice. They’ll just appreciate reducing cognitive load locally. I mean, at least that would be what I’d say. ¯_(ツ)_/¯


greg
2018-5-2 12:02:24

To clarify I mean style for #lang racket or #lang racket/base. Setting aside the tiny matter of what’s idiomatic for #lang looks-nothing-like lang-racket :slightly_smiling_face:


greg
2018-5-2 12:04:40

is OK with someone’s style provided they pass a Voight-Kampff test.


slack1
2018-5-2 12:08:52

Ah thanks!


timmstelzer
2018-5-2 14:12:30

@timmstelzer has joined the channel


timmstelzer
2018-5-2 20:24:43

Hey there! I’ve got a question regarding recursion; Just started doing euler problems to get into racket and was wondering if there is a better / “idiomatic” way to write this: https://github.com/tstelzer/problems/blob/master/racket/project-euler/problem-2.rkt#L11-L16?


timmstelzer
2018-5-2 20:27:27

Specifically, I was wondering how I can avoid that last expression ((loop)), it feels a bit redundant


samth
2018-5-2 21:04:49

@timmstelzer you probably want the let loop form


samth
2018-5-2 21:05:16
(let loop ([xs '()] [a 0] [b 1])
    (if (> (+ a b) ceil)
        xs
        (loop (stream-cons (+ a b) xs) b (+ a b)))))

lexi.lambda
2018-5-2 21:05:46

it’s also worth pointing out that you don’t get any laziness from streams with that loop


timmstelzer
2018-5-2 21:06:54

oh?


timmstelzer
2018-5-2 21:07:37

but when i run (stream-fib <some ceiling>) i get back a stream


timmstelzer
2018-5-2 21:07:45

doesn’t that imply that its lazy?


lexi.lambda
2018-5-2 21:08:22

no. the way you’re building up the list with an iterative loop means the entire stream is built before any value is produced.


timmstelzer
2018-5-2 21:08:40

ah hm


lexi.lambda
2018-5-2 21:08:49

you technically avoid evaluation of the (+ a b) expression inside the stream-cons form until the stream is realized, but that’s it.


lexi.lambda
2018-5-2 21:09:15

if you want a lazy version, you should make the loop non tail-recursive.


timmstelzer
2018-5-2 21:09:38

(i admit, i wasn’t aware that my loop was tail-recursive)


timmstelzer
2018-5-2 21:12:08

@samth nice, works!


lexi.lambda
2018-5-2 21:12:24

the Racket streams API is unfortunately rather inexpressive. the traditional way to formulate the fibonacci sequence with streams is something like: (define fibs (stream-cons 0 (stream-cons 1 (stream-map + fibs (stream-rest fibs))))) …but Racket’s stream-map only allows one stream argument.


lexi.lambda
2018-5-2 21:14:06

it also sadly doesn’t provide a stream-take-while function, and the one from srfi/41 doesn’t work with streams created with racket/stream.


timmstelzer
2018-5-2 21:14:07

hm, i see — this was a shot-in-the-dark anyways, haven’t worked with streams yet :slightly_smiling_face:


timmstelzer
2018-5-2 21:16:17

well, i can fortunately just remove all the stream- prefixes from my code and it will still work :smile:


timmstelzer
2018-5-2 21:16:28

though i do wonder about lazyness


lexi.lambda
2018-5-2 21:16:32

yeah. and in any case, if you want a version that still uses named let that’s actually lazy, you can do this: (define (stream-fibs ceil) (let loop ([a 0] [b 1]) (let ([c (+ a b)]) (if (> c ceil) empty-stream (stream-cons c (loop b c))))))


lexi.lambda
2018-5-2 21:17:42

but I think this misses out on why streams are nice, since a stream-take-while function would make it possible to define an infinite stream of fibonacci numbers without worrying about needing to take up to a certain condition.


timmstelzer
2018-5-2 21:18:00

hm true


timmstelzer
2018-5-2 21:18:48

thanks for the explanations, very much appreciate it!


slack1
2018-5-2 21:28:46

Do Racket people write their own take-while function then?


lexi.lambda
2018-5-2 21:29:00

I don’t think people actually use racket/stream


slack1
2018-5-2 21:29:04

oh


slack1
2018-5-2 21:29:11

What is a more standard solution?


slack1
2018-5-2 21:31:11

or just srfi 41?


lexi.lambda
2018-5-2 21:35:23

I don’t think Racket programmers often use lazy streams