Fork me on GitHub
#beginners
<
2022-06-13
>
Benjamin16:06:49

(read-string (prn-str (java.time.Instant/now)))
how do I do this correctly? Printing and reading timestamps, or other objects for that matter (guess it has something to do with reader tags)

dvingo17:06:14

the source is tiny, I found it incredibly helpful to see how to implement data reader literals

teodorlu20:06:01

Hey! Looking for feedback on a problem - wondering if there's an idiomatic solution I'm not seeing. I have a set of sources to get some data from. I want to try the sources in sequence, and find the first source that made sense. If that was the whole problem, I could do:

(or (source1) (source2) (source3))
. But I don't want to return just the return value from the function. I also want to tag where it came from! With a cond, it could look like this:
(cond
  (source1) [(source1) :source1]
  (source2) [(source2) :source2]
  (source3) [(source3) :source3])
Two problems with that solution: • (sourcex) is repeated in code. • We call (sourcex) twice - meaning we hit the network twice, which is unnecessary. --- How would you solve this?

teodorlu20:06:03

Alternative:

(or
 (when-let [s (source1)] [s :source1])
 (when-let [s (source2)] [s :source2])
 (when-let [s (source3)] [s :source3]))

teodorlu20:06:45

Or alternatively 1. Execute all of them in parallell 2. drop-while first element of tuple is nil.

hiredman20:06:19

have you ever seen the demo that got used to demonstrate channels when golang was first released?

teodorlu20:06:13

perhaps:

(->> [[:source1 source1] [:source2 source2] [:source3 source3]]
     (pmap (fn [kw action & args]
             [kw (apply action args)]))
     (keep second)
     second)
still way more code than the very simple (or (source1) (source2) (source3)).

hiredman20:06:31

having trouble finding it surprisingly

🙌 1
hiredman20:06:24

but the scenario is something like "you need to render google search results, the results come from N backend servers, fan out and only render results that don't timeout"

👍 1
hiredman20:06:12

https://golangbot.com/select/ has the simple version of that

👍 1
hiredman20:06:22

pmap is not something I am a fan of

hiredman20:06:44

it intermingles concurrent execution and lazy seq construction in a way that can be surprising, and doesn't expose the knobs I would want for controlling the parallel execution

teodorlu20:06:53

hmm. Yeah, I guess I'd be stuck once I needed something like timeouts. I haven't really had the chance to get properly into core.async or similar libraries / ways of thinking.

teodorlu20:06:25

looks like clojure.core.async is included with babashka - so that's an option.

hiredman20:06:08

core.async is not strictly required, but it will make it possible to do a pretty direct translation of the golang example

👍 1
kennytilton23:06:01

How did we get from "I want to try the sources in sequence..." to discussions of trying sources in parallel? Those are two different specs altogether.

👍 1
😄 1
didibus03:06:59

I'm guessing your question wasn't about parallelizing those. In that case, you can do:

(some second [[:source1 (source1)] [:source2 (source2)] [:source3 (source3)]])

👍 1
didibus03:06:41

Though... might need to think about the behavior with side-effects, not sure if it'll be chunked.

didibus03:06:57

Otherwise I would get too hung up on it and use your or with when-let combo or just use nested if-let

👍 1
teodorlu05:06:03

> How did we get from "I want to try the sources in sequence..." to discussions of trying sources in parallel? Those are two different specs altogether. > Scope creep 😁

Ben Sless13:06:48

You could write a tiny ad-hoc macro for this

1