that is a good idea.
will try that.
Is there a better way to write this?
(def urls {:yahoo "<https://www.yahoo.com>"
:google "<https://www.google.com>"})
(defn getter [url]
(future (slurp url)))
(reduce-kv (fn [acc name url] (assoc acc name (getter url))) {} URL)
;; write a another reduce to deref the futures.
That reduce-kv is fairly idiomatic to update all the map values; some projects end up with a helper that is named ala map-vals
(see e.g. https://weavejester.github.io/medley/medley.core.html#var-map-vals for a more "verbose" version with support for transients)
When you're going to reduce over a second time to deref the futures, you're going to be blocked by the slowest request; which I guess is OK, since you want all the return values together in one map
Which brings me to the elephant in the room - if you're writing some kind of "web scraper", slurp
is a really small hammer; most of the http client libraries (e.g. clj-http
, aleph
, etc.) support things like persistent connections, threadpooling, retries, better support for headers, etc. Things you'll probably need. The way it is written, if a single http request fails, the entire operation will fail and even if you try/catch the result, you will only get back a partial result (as far as you reduced; perhaps other requests finished but you didn't know about it)
Thank you. clj-http
looks a lot better.
I am trying to get this format output {:yahoo "...." :google "...."}
what is the clojure way to implement a function that does slightly different things based on a single argument to it being either a keyword or a function?
If your use case is simple, perhaps (if (keyword? x) (do …) (do …)) can work as well; Before jumping to things like defmulti I would question if I really need that fancy polymorphism in the first place.
I usually like to do the simplest thing that works, until it doesn’t.
Yeah, I ended up removing it later yesterday 🙂 But it was good that it worked for a while.
Helped me with refactoring something.
This is a thing I always wanted to do, when refactoring spaghetti code or callback hells, that i keep the old function as long as possible.
defmulti
thank you
(defmulti function (fn [arg]
(cond
(keyword? arg) :keyword
((some-fn ifn? fn?) arg) :function)))
(defmethod function :keyword [arg] )
(defmethod function :function [arg] )
(defmethod function :default [arg]
(ex-info "Unexpected argument" {:arg arg}))
not the best solution though, but might be handyThat's very helpful, thank you! I am reading the docs now and will experiment with it.
fwiw, I knew defmulti should be but I didn't realize I can't just ask type
on the argument but have to explicitly create another function to categorize the arguments and dispatch based on that other function instead of type
so I almost got sidetracked before your example cleared it up, thanks again
there is also nice addition to defmulti for repl-driven development
(defn dispatch-fn [& args])
(defmulti function #'dispatch-fn)
...
that give you ability to adjust dispatch function during development because implementation of defmulti looks like defonce from a distance.without it, changes in dispatch function of that form (defmulti function (fn …
will not be taken in account unless you explicitly eval something that overwrite function
var.
can't use repl driven development yet
so I am not sure what the whole thing is about since I have never seen anyone do what I do using repl driven development and I haven't done anything backend side with clojure. Are you saying that using the above pattern, if I change the defmulti form, that will update how the function works? I understand at least why I would have to eval something that overwrites function usually.
How do people layout cond ? Do do you:
(cond foo?
stuff
bar?
other-stuff
:else
do-else-thing)
Or:
(cond foo? stuff
bar? other-stuff
:else do-else-thing)
I find it gets messy when the code being executed for a predicate is multiple lines and can't finda way to lay it out that looks nice and is easy to see what code belongs to what predicatethanks, i wasn't aware of that guide
you should also get a lint/formatter for you editor which can do this for you.
Actually reading that, it seems like my cond should be a condp
Hi, I'm trying to create a selmer filter that can take multiple params.
maybe use split and pass them in with commas? or semicolons? kinda what i'm thinking
If it gets really large and unwieldy, I sometimes do:
(cond
pred?
stuff
bar?
other-stuff
:else
do-else-thing)
Is their a nicer way to do this?
(defn get-source-line-numbers [source]
(:line-nos (reduce (fn [{:keys [cur line-nos] :as acc} i]
(if (or (= "" i) (clojure.string/starts-with? i ";"))
(assoc acc :line-nos (str line-nos "\n"))
(-> acc
(assoc :line-nos (str line-nos cur "\n"))
(update :cur inc))))
{:cur 0 :line-nos ""}
(str/split-lines source))))
I have a control that has a multi-line string, I want a number allocated for each line that doesnt start with ;
or is blank. It's so I can number lines like this:Guess what I'm asking is if there is a way to do reduce but with a counter rather than create a map like I've done
In clojurescript, if I have a string stored in a variable, is it possible to get an element from that object based on that what's in that string? Like, say say:
(let [x "color"]
(. js/window -x))
But having -x
be replaced with -color
?I know I could use something like eval
to make it work, but it seems like that's way overkill in this situation.
Ah, oops, aget
is probably what I want.
(And aset
)
hmmm have you checked out reduce-kv
? not sure if it's helpful
If you’re accessing an object, use goog.object/get instead.
aget happens to work on objects too but should only be used on arrays
Oh interesting, okay. I wonder why that is.
Is there also goog.object/set
?
You bet there is one :) https://google.github.io/closure-library/api/goog.object.html
Ah, there's the api, thanks. 🙂
May I ask why this is preferred over aget
/`aset`?
I mean, I see that the docs say its for arrays. But I'm kind of curious about what differences there are (other than just style).
https://clojurescript.org/news/2017-07-14-checked-array-access
One problem that this creates is a challenge in further evolving aget
to match its intended purpose. A few examples that come to mind include:
• In Clojure, if you pass a non-integer array index to aget
, it will round down to the nearest integer. It would be nice to make ClojureScript’s aget
match this behavior. This is easily achievable by employing int
in the implementation, causing the emitted JavaScript to look like array[ndx|0]
. But this would break existing code that uses aget
for object property access.
• In Clojure, if you pass a negative array index, or one that is otherwise out-of-bounds, you’ll get an exception. It would be nice to consider adding such safety mechanisms to ClojureScript’s aget
. But again, any attempt to blindly treat the indices as numbers would run afoul of aget
being passed string indices.
• In the future, perhaps core library functions will have specs written for them. The same issues arise: The indices passed to aget
should satisfy the number?
predicate, but if that were done, lots of code in the wild would be deemed non-conformant.
Ah, that makes sense, thanks. 🙂