This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-09-23
Channels
- # announcements (2)
- # beginners (150)
- # calva (59)
- # cider (10)
- # clj-kondo (63)
- # cljs-dev (15)
- # cljsrn (34)
- # clojure (127)
- # clojure-dev (16)
- # clojure-europe (12)
- # clojure-italy (18)
- # clojure-nl (6)
- # clojure-russia (3)
- # clojure-uk (23)
- # clojurescript (18)
- # clojutre (15)
- # clr (2)
- # cursive (3)
- # datomic (26)
- # duct (6)
- # fulcro (9)
- # graalvm (3)
- # joker (9)
- # lambdaisland (1)
- # off-topic (12)
- # om (1)
- # pathom (29)
- # re-frame (16)
- # reagent (2)
- # shadow-cljs (57)
- # slack-help (2)
- # spacemacs (45)
- # sql (20)
- # xtdb (3)
- # yada (3)
Hi Everyone! I'm a begginer in Clojure, I've been practicing. And I think I'm ready to work fulltime on it. Anyone know begginer level jobs for an experienced Dev on other technologies?
Hi, everyone
If we have nested dosync
s would the inner dosync
s start a new transaction or not ?
(Is this sentence form the docs mentioning my question, I wasn't sure :
"Starts a transaction if none is already running on this thread.")
Thanks
All nested transactions get absorbed into the outer transaction. So the entire outer transaction is atomic, consistent and isolated from other transactions. The only reason I can come up with for caring whether inner transactions get started and/or retried atomically etc.. is if you have side effects in your transactions, which is a bad idea for multiple reasons. So I guess what I wanted to ask is, why do you care how inner transactions behave?
Thanks @U883WCP5Z
No I dont have sideeffects inside my transaction ... and what you described was the functionality that I hoped.
(I asked because I constructed transactions using multiple functions, each one having their own dosync
. So I wanted to make sure that they all get executed as part of a single transaction)
At the moment, I'm learning (tap> ....)
. I have, in my core.clj a (defn my-spy [message] (log/infof message))
. Then, throughout my code, at various places (to aid in debugging), I use (tap> "blah blah value blah blah")
. I'm wondering is there a pattern for better tap usage?
Hi. How would you apply a function to a generator so the generated value is the result of calling that function with generated values? I'll explain it better I have a function
(defn make-a-b [a b] {:a a :b b})
And a function
(defn add-c [a-b c] [(:a a-b) c (:b a-b)])
So for example I call
(def x-y (make-a-b 1 2))
x-y
;; => {:a 1, :b 2}
(add-c x-y 3)
;; => [1 3 2]
add-c
will only work if a-b
have :a
and :b
keys.
Now, I'm spec'ing add-c
to generate tests.
But I don't know how to spec that a-b
must be a result of calling make-a-b
with correct values.
I've tried this:
(def gen-a-b
(gen/tuple gen/string-alphanumeric gen/string-alphanumeric))
(gen/sample gen-a-b 3)
;; => (["" ""] ["" ""] ["" "hr"])
(s/def ::a-b
(s/with-gen
#(make-a-b (first %) (second %))
(constantly gen-a-b)))
(gen/sample (s/gen ::a-b) 3)
;; => (["" ""] ["" ""] ["" "hr"])
;; However, I'm expecting to receive something like this, instead:
;; => ({:a "" :b ""} {:a "" :b ""} {:a "" :b "hr"}
I want to do this so I can then go to add-c
specs and do:
(s/fdef add-c
:args (s/cat :a-b ::a-b
:c string?)
;; ...
)
So the generated tests generate parameters for :a-b
using the ::a-b
generatorI've looked at some code examples in the docs: https://clojuredocs.org/clojure.spec.alpha/with-gen And referenced to this Stack Overflow post: https://stackoverflow.com/questions/43348511/what-is-generative-testing-in-clojure
Thanks in advance.
re "How would you apply a function to a generator so the generated value is the result of calling that function with generated values?", that sounds like gen/fmap
sorry I didn't read all the rest
That's what I needed. It's fixed now. Thank you!
Hi everyone! I’m new to clojurescript stack coming from Javascript background. I’m just wondering what build tool do you prefer these days?
Based on what I’ve searched so far, figwheel-main
and shadow-cljs
are mostly being mentioned.
What are the pros & cons of each tool?
Can anyone also guide me what other tools do you use and for what purpose? Here are the tools that I’m aware of right now.
- reagent (like react)
- figwheel (webpack + npm ??)
- shadow-cljs (webpack + npm ??)
- leiningen (package manager?)
I address these questions and and more in https://betweentwoparens.com/start-a-clojurescript-app-from-scratch and Sean Corfield does an excellent job digging into lein, boot and clj here https://corfield.org/blog/2018/04/18/all-the-paths/
RE: figwheel v. shadowcljs
You can’t go wrong with either one. My preference is figwheel-main
. shadow
and figwheel
have the samw feature set minus the fact that shadow has built-in support for the npm ecosystem where as if you go with figwheel and want to make use of the npm ecosystem you would have to configure it yourself with webpack like this: https://clojurescript.org/guides/webpack
Short version: If you need to use npm packages then use shadow-cljs
. Otherwise use figwheel-main
.
For complex UI's and lifecycles use re-frame
, otherwise use reagent
There are always other options, but these are the most common at the moment.
@U6GNVEWQG THank you soo much 😃 How could I missed those articles?! Good read, very detailed and beginner friendly.
@U6GNVEWQG @U05254DQM I will use reagent for now. Between shadow-cljs
and figwheel-main
, it seems like only figwheel
has support for hot module reloading HMR
+ it supports npm
somehow
You can also use http://cljsjs.github.io/ to include JavaScript libraries as simply as Clojure dependencies, as it provides the externs
I recommend listening to https://clojurescriptpodcast.com/ for more background on ClojureScript and how everything works. This is run by a JavaScript developer who also does ClojureScript
thanks a lot @U05254DQM
how does (partition-by identity [coll])
work? It's de-duplicating the collection, but I can't find a way to get clojure to show me what it's doing step by step.
it's not deduping, but partitioning every time the input doesn't match the previous return value of the predicate (identity)
(partition-by identity [2 2 1 2 3 4 5])
=> ((2 2) (1) (2) (3) (4) (5))
It doesn’t.
Partitioning into a list of collection, splitting whenever the element changes.
It’s iterating over the collection entries. Look at the source, but beware: nobody wants to know how the sausage is made.
Absolutely!
([f coll]
(lazy-seq
(when-let [s (seq coll)]
(let [fst (first s)
fv (f fst)
run (cons fst (take-while #(= fv (f %)) (next s)))]
(cons run (partition-by f (lazy-seq (drop (count run) s))))))))
that's the relevant part of the sourceIt’s highly optimized
@ghadi when you look at the full sources, it makes use of volatile and reducers.
I'm trying to get an intuition on what partition-by
is doing. The clojure doc says that it splits each time the function (in this case identity
) returns a new value
de-duping would mean that input items are omitted from the output collection, but partition-by doesn't remove anything, just splits whenever the input changes
identity
makes partition-by
compare by the actual collection value.
whenever that changes, it add another list to the result.
the word collection is also confusing the example -- partition-by examines individual inputs of the input collection
user=> (partition-by #(< % 10) [0 1 5 10 12 14 0 20 0])
((0 1 5) (10 12 14) (0) (20) (0))
so is the comparison in @ordnungswidrig example [2 2 1 2 3 4 5]
vs [2 2 1 2 3 4 5]
the predicate in that example returns true or false, and partition-by splits things up every transition from t->f or f->t
@watchtheblur no, it’s comparing 2
vs. 2
then 2
vs. 1
I see.
one possible way is to copy the definition of a function to your own, with a different name, and modify it, e.g. add println or other kinds of debugging statements to it. Then try calling your modified version to see what happens, starting with small inputs.
Another is to use a source level debugger that can step through the execution, but I cannot recommend a particular one as I haven't used one.
so for @ordnungswidrig example, the 2 from f is compared with the 2 from the t predicate first, then the 2 from f is comparing the 1 from the t (skipping the second 2). and so on?
uhhhm, I guess it starts with 2 2
giving ((2 2)))
, then 2 1
giving ((2 2) (1))
@andy.fingerhut Thanks for the suggestions, I'll try both!
When adding println statements, note that you should be able to take any expression like (x y z)
anywhere in the code, and change it to (do (println "I want to know x=" x "and y=" y "but I don't care about z") (x y z))
. The (do ...)
expression evaluates all of its subexpressions in the order given, then returns the value of the last one.
@watchtheblur the predicate is never called on the collection, only on individual elements of the collection
(defn pb [f coll]
(reductions (fn [result x]
(if (= (f x) (some-> result last first f))
(cons (cons x (last result)) (butlast result))
(cons (list x) result)))
nil
coll))
This is an example implementation of what is logically happening. I used reductions
so it will return a list of the intermediate results instead.
(Does not work correctly with empty collection, but you might get the idea)
Thanks @ordnungswidrig! I'll study that code. (It'll take a while :p)
and thanks @andy.fingerhut and @ghadi!
As part of solving a 4Clojure challenge, I implement a simplified version of partition in this video. I also set through the code with a debugger, so you can see exactly what the code is doing.
https://www.youtube.com/watch?v=ThIxwQeSdTs&list=PLpr9V-R8ZxiDjyU7cQYWOEFBDR1t7t0wv&index=37
There are many more videos in the playlist, hopefully you find them of interest. Feel free to ask if you have questions (I like to try make these videos better)
Thanks @U05254DQM! I took a look at https://practicalli.github.io and also found your other 4clojure series. Really great content that you're making, I really appreciate it! I can't watch your live recordings because of timezone difference. I was wondering if you know of a way to find clojure study groups, virtual and/or in person?
Try searching for Clojure on http://meetup.com and take a look at the #events channel for anything local to you.
There is also #remote-meetup
Thanks for the suggestions @U05254DQM! I'll check them out!
@watchtheblur Does this help explain the behavior?
user=> (defn id-print [x] (println "looking at" x) x)
#'user/id-print
user=> (partition-by id-print [2 2 1 2 4 3 5])
(looking at 2
looking at 2
looking at 1
looking at 1
(2 2) looking at 2
looking at 2
(1) looking at 4
looking at 4
(2) looking at 3
looking at 3
(4) looking at 5
looking at 5
(3) (5))
user=> (defn even-print? [n] (println "looking at" n "is it even?" (even? n)) (even? n))
#'user/even-print?
user=> (partition-by even-print? [2 2 1 2 4 3 5])
(looking at 2 is it even? true
looking at 2 is it even? true
looking at 1 is it even? false
looking at 1 is it even? false
(2 2) looking at 2 is it even? true
looking at 2 is it even? true
(1) looking at 4 is it even? true
looking at 3 is it even? false
looking at 3 is it even? false
(2 4) looking at 5 is it even? false
(3 5))
user=>
This shows that the predicate may be called more times than there are elements in the collection but it also shows how the partitioning changes based on the result of the predicate.Wow! That's what I was looking for! I was looking for a way to see the stack, but this gives me a hint at how to understand the process. Thanks @U04V70XH6!
Hi @U04V70XH6, I ran your code in a repl, but got a slightly different output. I was wondering if you had any insight on why they are different? Here's mine:
(defn id-print [x] (println "looking at" x) x)
=> #'cursive-test.core/id-print
(partition-by id-print [2 2 1 2 4 3 5])
looking at 2
looking at 2
looking at 1
looking at 1
looking at 2
looking at 2
looking at 4
looking at 4
looking at 3
looking at 3
looking at 5
looking at 5
=> ((2 2) (1) (2) (4) (3) (5))
What repl was that?
I'm guessing Cursive -- and it's messing with the output, separating stdout and results, which obscures what is really going on.
yeah, I tried it in cursive, and then also windows command line prompt using lein repl
Both had the same output. Should I try it lein repl on a linux platform?
Ahh, I figured it out. I was using something called "nREPL" via cursive. Once I switched to clojure.main, I got the same output. Thanks again @U04V70XH6!
When trying to understand the behavior of something in Clojure, it's often worthwhile to use the CLI/`deps.edn` command line REPL just to ensure no tooling is messing with your results. Cursive, in particular, tries to "help" by managing the REPL experience more tightly -- and nREPL-based tooling often adds middleware to customize the behavior of evaluation.
Argh. How do I refer to the thing being mapped in a map call? I’m likely very confused, but something like (map (print (str % ”is a thing”)) [”something” ”else”]) if that makes sense.
(print ...) returns nil, which isn't callable as a function
more precisely you might say you map over a seq or something seqable (map internally calls seq on whatever you pass in)
I'm calling my spec-check tests like this:
(deftest subway-line-test
"Check subway-line"
(is (sc/spec-check `subway-line {})))
(t/check `subway-line)
How could I specify the :num-tests ?
I tried adding that key-val to {} in the deftest:
(deftest subway-line-test
"Check subway-line"
(is (sc/spec-check `subway-line {:num-tests 100})))
But doesn't work.
How could I achieve it?what is that spec-check
function?
Found here. https://ask.clojure.org/index.php/8590/clojure-spec-alpha-check-inside-clojure-testing-framework
(defn spec-check [fn-to-check options]
(let [results (t/check [fn-to-check] options)]
(if (some :failure results)
(do
(println "\nFailed specs:")
(doseq [result results
:when (:failure result)]
(println (:sym result))
(pp/pprint (or (ex-data (:failure result))
(:failure result)))))
true)))
Ah, OK, so you are using my suggested function...
Haha, yes.
Hmm, now that I realize, the two calls are not even related.
That check
function does not take a :num-tests
option.
I was testing two times. One with the spec-check function and one with check
.
Funny how I didn't even realize that.
Thanks.
I think you need {:clojure.spec.test.check/opts {:num-tests 100}}
That worked. Thanks!
Hello! I am trying to convert:
(do-stuff x y :a "a" :b "b" :c "c")
to something more like:
(def value-set [[:a "a" :b "b" :c "c"]]
(loop [i 1]
(do-stuff x y (nth value-set i))
(if should-recur (recur (inc i)))
How would I do that? Assume I can't change do-stuff
, but anything else is fair game. I tried looking at apply
, but that isn't quite going to work here.unfortunately you would have to do something like a macroexpansion to get that to work
(apply (partial do-stuff x y) (nth value-set i))
maybe?
your best bet is to define a new function that wraps do-stuff
with one that takes your vector (or map, or whatever)
Actually, it looks like @christian.gonzalez’s solution works.
it’s the same thing as what @lilactown suggests, wrapping do-stuff
doesn’t apply work though? (apply do-stuff x y (nth-value-set i))
i just tried in repl it seemed to work for a small example i made
https://clojuredocs.org/clojure.core/apply has some examples (apply f args) (apply f x args) (apply f x y args)
ahh yeah tricky =P
apply takes in a function, when you wrap in parens it will evaluate
and not necessarily return a function
I've not had to mess with unlimited arity before, let alone in clojure, wasn't really sure how to pass a vector into the & args
good resource for that here https://clojure.org/guides/learn/functions
The madness you've helped me construct:
(apply are [x y] (= (attr driver :name (name x) :value) y)
(nth sled-settings-gui-values (dec slot-number)))
But, it let's me loop through doing the same process and be able to feed a different set of values in for each iteration.
the vector you’re passing in has a fixed length?
you’ll have to wrap that macro in a function i think
i don’t know how to handle a variable number of args though
Was thinking of something like this (apply #(some-macro %1 %2 %3) [1 2 3])
not sure about the %&
here