This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-10-24
Channels
- # arachne (1)
- # aws (1)
- # beginners (43)
- # boot (67)
- # cider (7)
- # cljs-dev (14)
- # cljsjs (6)
- # clojure (215)
- # clojure-czech (2)
- # clojure-dev (12)
- # clojure-dusseldorf (2)
- # clojure-italy (1)
- # clojure-russia (22)
- # clojure-spec (2)
- # clojure-uk (33)
- # clojurescript (85)
- # cryogen (2)
- # cursive (1)
- # datascript (22)
- # datomic (18)
- # dirac (8)
- # hoplon (9)
- # klipse (1)
- # lein-figwheel (5)
- # leiningen (126)
- # off-topic (1)
- # om (57)
- # onyx (159)
- # pedestal (33)
- # planck (2)
- # re-frame (52)
- # reagent (3)
- # ring (2)
- # ring-swagger (16)
- # test-check (12)
- # testing (5)
- # untangled (86)
- # vim (6)
@credulous Replace the loop with a (fn [values] (let [...] (assoc ....))
, then call it with (iterate the-fn v)
and then you can take from it lazily
why am I unable to do this:
(case (class "randomstring")
String (println "I'm a string")
Long (println "I'm a long"))
?@vandr0iy why you use case
? if
should do what you want
(defn check-string [x]
(if (instance? String x)
"Yes"
"No»))
it's an example, in my source I'm comparing a totally another object (I'm working on coda hale metrics). What I'm asking is: why am I unable to call 'case' on a class?
may be this explain it? — https://clojuredocs.org/clojure.core/case
The test-constants are not evaluated. They must be compile-time
literals, and need not be quoted. If the expression is equal to a
test-constant, the corresponding result-expr is returned. A single
default expression can follow the clauses, and its value will be
returned if no clause matches. If no default expression is provided
and no clause matches, an IllegalArgumentException is thrown.
yeah, that might be it. I thought that String
or Long
represented the class directly, and wouldn't need any kind of evaluation... Thanks.
This is meta-info, I use this for type hint, like «pre-assert» in function. So, for you question, I think that’s doesn’t help 😞
sigh... i hate tranforming things just for the sake of comparison, but probably this is the case where I should stringify my (class my-value)
...
Thank you for your help!
is it considered idiomatic to have a function that would take more than 1 arg to instead take a map? so that way the order of arguments doesn’t become an issue?
i refactored an exercise from clojure from the ground up this way after encountering an order or args related error
user> (first (most-prevalent-crimes {:data-file "2008.json" :crime :arson}))
{:report-count 42, :county "NV, Carson City", :prevalence 7.732528E-4, :county-population 54316}
user> (first (most-prevalent-crimes {:crime :arson :data-file "2008.json"}))
{:report-count 42, :county "NV, Carson City", :prevalence 7.732528E-4, :county-population 54316}
@chadhs yes no problem, I do it a lot
it's also a great way to pass around data or configuration without imposing knowledge on the intermediaries
i suppose then you’d want to make sure to put an example in the docstring so you don’t have to read the function to figure out what needs to go in arg-map
or whatever one would call it
@chadhs or use clojure.spec 🙂
you can also (and you often will) perform destructuring in the arguments list, which will make the schema of the map more obvious
@chadhs one way this is commonly done is with “kwargs” - a function defined like (defn most-prevalent-crimes [& opts] (let [{:keys [data-file crime]} opts] …))
opts is a sequence of key-value options but is destructured as a map
you would invoke that like (most-prevalent-crimes :data-file “2008.json” :crime :arson)
because you are destructuring to an (unordered) map, you can pass the options in any order
As an addition, what I usually do, is separate parameters by type, where one type is the data passed around and another type could be the database connection or another component that I might be using
@val_waeselynck i’ve yet to dive in the pool, but it’s on my list.
this is primarily used for options where some can be omitted and is a useful technique for the outer layers of an API
@alexmiller super helpful; i’ll do a quick refactor; thank you 🙂
but is often discouraged for internal layers, where it’s better to just pass a map - this ends up being easier to pass through other downstream functions than reassembling the flattened opts
the other thing it enables is using a destructuring :or
clause in the map destructuring to provide defaults
(defn most-prevalent-crimes [& {:keys [data-file crime] :or {crime :arson}}] … )
so that makes :arson the default :crime and you can omit that option
when calling most-prevalent-crimes
if you’re using spec, it has support for spec’ing this kind of function too with keys*
i’ve not used spec yet; but i did just listen to the episode of defn
you were on so on my list to try soon @alexmiller 🙂
(s/def ::crime #{:arson :theft})
(s/def ::data-file string?)
(s/fdef most-prevalent-crimes
:args (s/keys* :req-un [::crime ::data-file])
:ret (s/coll-of ::info))
start of a spec for that fn above (obviously incomplete)
i capturing all this in OmniFocus to review later when I have more time to play so all very helpful; thank you
@vandr0iy Java classes are not constants and can’t be used as case
options - they must be loaded by a classloader and there can be multiple ones in play (one per classloader) in a JVM
@vandr0iy if you are looking to dispatch based on type, protocols are the fastest way to do so in Clojure (as they leverage the highly optimized JVM machinery for virtual dispatch in the JVM)