This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-08
Channels
- # alda (1)
- # announcements (18)
- # babashka (101)
- # beginners (110)
- # calva (17)
- # cider (53)
- # clara (18)
- # clj-kondo (26)
- # cljdoc (6)
- # clojure (152)
- # clojure-europe (9)
- # clojure-portugal (4)
- # clojure-spec (20)
- # clojure-survey (7)
- # clojure-sweden (10)
- # clojure-uk (10)
- # clojured (1)
- # clojurescript (29)
- # core-async (7)
- # cursive (4)
- # datomic (11)
- # defnpodcast (2)
- # dirac (1)
- # emacs (13)
- # events (2)
- # figwheel-main (1)
- # fulcro (1)
- # jobs (14)
- # jobs-discuss (17)
- # leiningen (2)
- # malli (1)
- # off-topic (74)
- # overtone (1)
- # pedestal (4)
- # planck (2)
- # re-frame (7)
- # reitit (4)
- # remote-jobs (4)
- # shadow-cljs (78)
- # slack-help (3)
- # spacemacs (56)
- # test-check (3)
- # tools-deps (6)
Yeah, I think so. It's very useful for writing your own exception pretty printer 🙂
The direction keys(2,4,6,8) within the Numerical Keypad on Ubuntu(Cursive) doesn't display history of commands on the repl. Same keys works on the terminal(Ubuntu), and also on Windows(Cursive). Has anyone noticed similar something similar maybe?
There is a #cursive channel you may wish to try asking in.
Which method is better? I prefer the count as it's more concise but I've seen a few code examples using the reduce +
method? Is it more efficient?
Efficiency is probably about the same for both. Both create one lazy seq each.
A more efficient alternative could be (*x*/count (*filter*
*even?*) coll)
using the xforms library. This uses the transducer returning arity of filter
. This particular example is not all that elaborate and I don't think will result in a huge win though. (Benchmark comparison in thread)
user=> (require '[net.cgrand.xforms :as x]
'[criterium.core :as crit])
nil
user=> (crit/quick-bench (count (filter even? (range 100))))
Evaluation count : 239082 in 6 samples of 39847 calls.
nil
Execution time mean : 2.643472 µs
Execution time std-deviation : 81.013434 ns
Execution time lower quantile : 2.559159 µs ( 2.5%)
Execution time upper quantile : 2.760176 µs (97.5%)
Overhead used : 9.031450 ns
Found 1 outliers in 6 samples (16.6667 %)
low-severe 1 (16.6667 %)
Variance from outliers : 13.8889 % Variance is moderately inflated by outliers
user=> (crit/quick-bench (x/count (filter even?) (range 100)))
Evaluation count : 1124898 in 6 samples of 187483 calls.
nil
Execution time mean : 541.007719 ns
Execution time std-deviation : 38.221458 ns
Execution time lower quantile : 514.929972 ns ( 2.5%)
Execution time upper quantile : 598.902050 ns (97.5%)
Overhead used : 9.031450 ns
when dealing with a PersistentMap
in an atom
, is it preferable to pass the atom to my function and deref
at the point of use, or deref and pass the value into the function?
I find it be a good policy to minimize the number of functions that touch stateful things, so generally I think you should prefer the latter
on single use, it does not matter. On multiple use in the function, me personally I would deref once in let
(update ctx :body v)
is this update
wrong?ctx
is a map
is v
a function that takes the current body?
or is it the new value?
I 'm trying to update :body
for the value of v, wich is a map. but :body is always getting nil
v is the new value
"update" is for a function, taking the old value and returning a new one
you want assoc
Am i able to have 2 assocs, one after other?
yes, but also you can just put multiple keys in one assoc
user=> (assoc {:a 0} :b 1 :c 2)
{:a 0, :b 1, :c 2}
important to note: assoc doesn't modify its argument, it returns a new map
Ok, i'm couting with it
I already have immutabily on my mind
@ramon.rios the reason you get that result:
user=> ({:a 0 :b 1} :c)
nil
a hash-map is a function on its own keys, returning nil for not foundThank you friend
assoc
resolve it
Is there clojure library for Twilio SMS API that actually works?
it's a REST api, I'd just use clj-http
Is there a way to alter session duration with ring? I'd like sessions to be basically perpetual but i don't know if there's a built-in timeout someplace. i also want to figure out how to update my static pages without restarting my server, but they are rendered from a vector
@sova it's documented here https://github.com/ring-clojure/ring/wiki/Sessions
(def app
(wrap-session handler {:cookie-attrs {:max-age 3600}}))
so you can add :cookie-attrs as an extra arg to wrap-session
okay let me see thank you
` (defn -main [ & args] (server/run-server (wrap-cors (wrap-defaults all-routes site-defaults)) {:port 8117}) (println "server on @ localhost:8117"))`
wrap-defaults
is a boilerplate that includes wrap-session, once you customize one of the wrappers you probably want to stop using wrap-defaults
Thanks for your help, the middleware is still my achilles heel.
so you'd usually have something like (def site-handlers (-> all-routes (wrap-defaults site-defaults) (wrap-foo) (wrap-session {:cookie-attrs ...}))
where each middleware returns a new handler to replace the one made by the step before it
i notice a (wrap-foo)
in there...
Nice. my kingdom for a flowchart
right, you'd do that for each handler that wrap-defaults has - since you want to replace the configs for one of the wrap-defaults middlewares
Okay, so everything wrap-defaults does has to be covered by another one that passes a finished map along ?
wrap-defaults is nice when you don't need to change any of the defaults, but luckily all it is is a bunch of stacked middleware, easy to replace
that chain isn't passing a map, each wrapper returns a replacement for your handler, and you use the last one
Oh. Neat. That makes more [functional] sense
purely additive
this is a prototypical midddleware:
(defn wrap-foo [old-handler] (fn [request] (f (old-handler (g request))))
where f modifies the result of old-handler, and g modifies the input of old-handler
of course most middleware don't do both - most only modify the result
so by calling wrap-foo you are basically doing aop, and making a new function that does what the old handler does, and also calls f and g
neat. almost graspable, still a little mind-bending
i'm trying to think of a realworld analogy
it's a car wash that can optionally modify the car before it goes in
in aop g is called a "pre-hook" and f is called a "post-hook" iirc
it's the fancy name for what ring middlewares do (arguably) https://en.wikipedia.org/wiki/Aspect-oriented_programming
quick question regarding namespaces: i have a test namespace called game.core-test
, which I'm using at the moment to hold all of my test helper functions and set up/tear down logic that's used in the rest of my test suite. but seeing as I have a game.core
namespace already, this feels messy. Is there a common idiom/namespace for the test utility files?
I mention AOP because it's a pretty well documented programming pattern / paradigm, and it does what we do in middleware
so it can help in understanding the pattern (hopefully)
I checked the style guide, but they didn't have much for tests or test namespaces
I would add test/game/fixtures.clj
and add all the helpers etc in there...
and then import that into each of my test files?
idiomatically game.core-test
should be under test/
rather than src/
and should have unit tests for game.core
it is, i have the separate test/
folder which otherwise matches the folder structure of my src/
folder
I just want one massive handler object with flags for everything ... maybe i am too lazy even for clojure xD
@sova that's closer to what interceptors
in pedestal do - the advantage are they are data which is queryable / updatable etc., the disadvantage is they require an execution model on top of that data, where ring middleware are just functions that return functions
nothing stops you from pulling in pedestal's interceptor lib and turning each middleware into an interceptor etc. - but that might also be a waste of your time :D
@sova I think you might want Yada: https://juxt.pro/yada/manual/index.html
> Yada’s model is to provide a complete and correct HTTP response to a request. Ring and Pedestal models piece together partially correct responses based on small transformations in middleware or interceptors. From: https://purelyfunctional.tv/mini-guide/clojure-web-servers/
@sova > It achieves this by providing you with a highly-configurable handler that is general enough to use in the vast majority of cases. Rather than coding the handler, the developer only has to configure one. This declarative approach provides greater scope for accuracy, consistency and re-use. Definitly sounds like exactly what you asked for :p
Rock solid!
i just threw wrap-session in there for now... but i will consider yada in my next project which will be fairly soon
Hi, is there some Clojurescript library to parse css strings in hiccups? I need to transform them into maps for Reagent.
hmmm neat question
I was using str/split for : and ;, but it fails on things like
background: url("data:image/jpeg;base64,.....");
I have made a simple defn-spy
macro, that wraps a function and saves it's arguments and return value in an atom every time the function is called.
(defmacro defn-spy [& args]
(let [f (fn [name params body]
`(defn ~name ~params
(let [result# (do ~@body)]
(swap! spy-atom update (symbol (quote ~name))
(fn [calls#]
(conj calls# [~params result#])))
result#)))]
(if (string? (second args))
(let [[name _doc params & body] args]
(f name params body))
(let [[name params & body] args]
(f name params body)))))
Before the function f
in the let was the whole macro, but as I had to take into account functions with a docstring I had to write an if
to handle those two cases (with and without docstring). Any idea how to write it better?without speaking to the macro itself, this idea can be accomplished dynamically without a macro by using alter-var-root
I did a quick hacky solution to solve the problem I found, if someone else is intersted:
(defn append-char
"Appends the given character to the last string in tokens."
[tokens ch]
(update tokens (dec (count tokens)) str ch))
(defn parse-style
"Parses a style value from a string."
[style]
(->> style (reduce (fn [[tokens inside-string] char]
(let [str-char (str char)]
(cond (= str-char "\"") [(append-char tokens str-char) (not inside-string)]
(and (#{":" ";"} str-char) (not inside-string)) [(conj tokens "") inside-string]
:else [(append-char tokens str-char) inside-string]))) [[""] nil])
first butlast (map str/trim) (partition 2 2)
(map (fn [[k v]]
[(keyword k) v]))
(into {})))

Didn’t realize this article existed: https://blog.cleancoder.com/uncle-bob/2019/08/22/WhyClojure.html
In ClojureScript, are their performance benefits to use amap/areduce vs map/reduce?
map is lazy , amap forces a full array to be assigned right then... if you can ensure the array never has to grow maybe amap is smart(er) marginally, but if you are unsure of the number of elements map is just as good or better ... someone with experience correct me if i'm wrong
When you eval a string from read-string, are all the symbols qualified vs the symbols required and referred in that namespace, or is it only against the symbols in clojure.core?
however people often don't understand the different parts of runtime vs. compile time state that effect how symbols are resolved
specifically, when you define a namespace in a file, it is the current namespace (`*ns*`) only while it is being loaded, after which, presumably when you are actually running your code, it is not the current namespace, so things that use the current namespace for symbol resolution (like the compiler which is what eval calls) don't know anything about aliases or imports or whatever in your namespace because at runtime the current namespace is not your namespace
this can be confusing because the repl preserves the current namespace between calls to eval
So if I have a function in namespace a that calls eval on a list, then when the function that is actually called, the compiler might not be using the namespace the function is in?
In other words, despite the function being in namespace a, the compiler doesn't use namespace a for evaluation.
at runtime the most common current namespace is clojure.core, just because that is the default value of *ns*
Hmm, so do I need to specify the namespace as part of the function before eval?
I should have joined this slack a couple years ago. All of that is new to me
that way you can capture the load/compile time value of *ns*
as a runtime value that won't change
Most people avoid using eval
and so a lot of these issues don't arise for them.
Thanks @hiredman , that got me past a hurdle.