This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-01-16
Channels
- # announcements (2)
- # beginners (50)
- # boot (80)
- # calva (4)
- # cider (58)
- # cljs-dev (11)
- # clojure (140)
- # clojure-brasil (1)
- # clojure-denver (1)
- # clojure-dev (10)
- # clojure-europe (8)
- # clojure-finland (2)
- # clojure-italy (5)
- # clojure-nl (2)
- # clojure-quebec (1)
- # clojure-spec (2)
- # clojure-sweden (4)
- # clojure-uk (94)
- # clojurescript (98)
- # cursive (19)
- # data-science (1)
- # datascript (9)
- # datomic (43)
- # emacs (2)
- # fulcro (29)
- # graphql (41)
- # hoplon (15)
- # jobs (2)
- # kaocha (4)
- # liberator (24)
- # off-topic (9)
- # perun (1)
- # re-frame (11)
- # reagent (17)
- # reitit (8)
- # remote-jobs (2)
- # rum (2)
- # shadow-cljs (24)
- # spacemacs (1)
- # specter (1)
- # tools-deps (21)
Hi all! Extreme noob to Clojure here. Cider aside.. which dev environment is most suited for beginner Counterclockwise/ Cursive ? Any links on how to setup a dev environment ?
I'd recommend Cursive. It's been the most complete environment for me and gets solid updates. Other environments I've been left in a broken state when the developer(s) of the tool get upset that something changed in core and they leave instead of fixing it. I can't deal with that instability.
absolutely @UAFT1B7Q8
Thanks!
Counterclockwise hasn’t seen much love in the past years and so getting support for issues you run into might be difficult
CCW is no longer developed and I don’t think works on newer versions of Java/Clojure
If you use emacs, use Cider. If Intellij use Cursive. If none, use Cursive, because Intellij is easier than emacs. You don’t want to learn hard editor + Clojure at the same time.
I would love to see stable and extended Clojure plugin for Visual Studio Code. But today you can choose only between emacs + cider / Intellij = Cursive I guess.
If you already use Atom, look at Chlorine or ProtoREPL. If you already use VS Code, use Calva. The main thing you want for learning Clojure is an integration between your editor and a REPL, so you can just hit a key combo and evaluate a form, a top-level form, or the entire file into that REPL — without typing into the REPL. All of those are sufficient.
I don't know about Chlorine, but I know ProtoRepl doesn't really support ClojureScript. If the person is only writing Clojure then it works well.
My understanding is that Chlorine is great if you're using shadow-cljs
but not other ClojureScript build/dev tools. Since Chlorine is written in cljs and uses shadow-cljs
and that's how it is developed (using itself).
Well that's good to know. I use shadow-cljs myself, but the issue is if I need to use some other tool for whatever reason then now I have to change my entire development environment over a tool being switched out. That's disruptive.
Go open an issue on the Chlorine repo then 🙂
I'm pretty sure the maintainer is very open to supporting a broader set of cljs workflows. He seems very receptive and helpful in the #chlorine channel.
That's great, but the reality is that it only supports one tool and thus creates this situation. I'm sure I'm not the first to address such a concern. If that changes in the future I'd be happy to check it out.
(and if you use vim, look at fireplace? I’m not familiar with the vim/Clojure ecosystem, sorry)
For beginners, not having to struggle with the basics of an editor is a big help 🙂
A macro question:
(defmacro transact!
""
[& body]
`(jdbc/with-db-transaction [conn# db]
~@(map (fn [transaction]
`(jdbc/execute! conn# ~(honeysql/format transaction)))
body)))
> (macroexpand-1 '(transact!
(-> (insert-into :foo)
(values [{:id (java.util.UUID/randomUUID)}]))))
=>
(clojure.java.jdbc/with-db-transaction
[conn__27812__auto__ db-adapter.sqlite/db]
(clojure.java.jdbc/execute!
conn__27811__auto__
(honeysql.core/format
(->
(insert-into :foo)
(values [{:id (java.util.UUID/randomUUID)}])))))
The inner conn#
, expanded, is a different one than the outer conn#
. How to make the conn#
s the same symbol?@timrichardt it has to do with the two layers of quoting
(defmacro foo
[& body]
`(let [conn# ~body]
(prn conn#)))
;; conn# is the same
(defmacro foo
[& body]
`(let [conn# ~body]
`(prn conn#)))
;; conn# is different
Yep, it is the layering but removing the quoting does not work in this case. Because the map
is evaluated, it tries to evaluate conn#
at compile time which is not possible.
@timrichardt I would make the macro
(jdbc/with-db-transaction [conn# db] (doto conn# ~@(map (fn [transaction] `(jdbc/execute! ~(honeysql/format transaction))))))
<-- admittedly just avoids the problemcan you use a let binding in the macro to capture conn#
and then use that common binding in both quoted forms?
an example: https://github.com/ztellman/manifold/blob/master/src/manifold/deferred.clj#L309-L325
@dpsutton Great, this seems to be the solution around this multi-layer-macro problem.
i think ztellman solves this problem as well in ridley with a way to unify gensyms across quote boundaries like this
@eraserhd Thanks, this works too, great.
@timrichardt read this section of zach's Potemkin library: https://github.com/ztellman/potemkin#unify-gensyms (not advocating use necessarily. not advocating use but he for sure has thought of a great many problems)
Is there any way to collect the statistics from a criterium
benchmark? Trying to determine the time complexity of an algorithm by running it against different inptus
@qythium not sure what you mean by statistics, but if you referring to the outputs of e.g. bench
, run it against all your inputs inside with-out-str
and transform/write the resulting string somewhere.
Strange to have to write a parser when surely those values are around as actual numbers somewhere? I tried searching through the documentation but couldn't find anything
@qythium Yep, thats stupid 🙂 criterium.core/benchmark
returns the result as data http://hugoduncan.org/criterium/0.4/api/criterium.core.html#var-benchmark
(def timing-results
(doall
(for [n [5 10 15 20]]
(criterium/quick-benchmark
(fib n) nil))))
(map #(get-in % [:mean 0]) timing-results)
;; =>
;; (6.82956017409221E-7
;; 8.839126734896198E-6
;; 1.0012795602974459E-4
;; 0.0010987932789473685)
now to write a function which will look at that and estimate if it's O(n), O(n^2), O(n! log (n)) , etc.:thinking_face:
That is probably more tricky than you would expect. I wouldn’t be surprised if there are mathematicians who spend their lives on that.
Yep, especially since you will see things in the curve, that are due to the machine, not the ideal algorithm. E.g. jumps when certain chunk sizes are passed etc. Mathematicians usually don't care about such things.
Yeah, I don't need it to be very rigorous, just using this as a way of getting my head around the performance characteristics of core.logic
programs - which seem really hard to reason about and blow up exponentially in unexpected ways.
I ended up just hacking together something in Python notebook which plots out the points and the regression lines for logn n, nlogn, n^2 , 2^n
, then eyeball which curve fits best 😅
why would I be getting an error about manifest type when depending on a git source?
cider/piggieback {:git/url ""
:sha "fd99b9e3cfd2069a2484ba9e75dcd1bb04b78ed8"}
Error building classpath. Manifest type not detected when finding deps for cider/piggieback in coordinate {:git/url "", :sha "fd99b9e3cfd2069a2484ba9e75dcd1bb04b78ed8"}
seems like we're not quite there yet, but at this point I'm creating extra work for you, so I'll just pull it down and see if it works with a local dependency
{:git/url "https://github.com/dpsutton/piggieback.git" :sha "403142e5017628ce447aebf2e4c0c82d482488c3"} same error with that
tools.deps is trying to determine the transitive dependencies for piggieback, but is not finding a manifest it understands (deps.edn or pom.xml)
currently tools.deps doesn’t know how to read lein project.clj files
one option is to forcibly declare it as a deps.edn project (it then treats a missing deps.edn as no transitive deps)
you can do this by adding :deps/manifest :deps
to your coordinate
you could
make sure you move your sha then
the generated pom just isn’t including your source files
you could just use a deps.edn file like:
{:deps
{org.clojure/clojure {:mvn/version "1.8.0"}
org.clojure/clojurescript {:mvn/version "1.9.946"}
nrepl {:mvn/version "0.4.5"}}}
probably don’t even need nrepl there
oh, maybe you do, not sure
assumes src dir without explicitly putting that? I think it was lacking dirs from the lein generated pom due to profiles
by default it uses src
as the source directory
but you could add :paths ["src"]
to be explicit
thanks for the help @alexmiller
If I’m using doto
, is there a clearer way to call doseq
inside of it instead of wrapping an anonymous function in a function literal? If I want to use doto
right now I have to do this -
(doto (Ctor.)
(#(doseq [[a b] c]
(.aMethod % a b))))
Leaning towards just doing this because I think it reads better -
(let [obj (Ctor.)]
(do
(doseq [[a b] c]
(.aMethod obj a b))
obj))
let already has an implicit do in the body btw, so using do there is redundant
that is assuming c isn't static, if c is a known value, I would write some code to generate the method calls and just paste them in
(dorun (map (comp (partial apply .aMethod)
(juxt (constantly obj) first second)) c))
as a small thing, you can replace (dorun (map ...))
with (run! ...)
Feel like that’s going to generate reflection warnings?
Our project fails compilation if there are any reflection warnings, but I’ve never tried apply .someJavaMethod
that simply doesn't work
Yeahh seemed dubious haha
Also people on my team would hate me for that
. is an interop form, on compilation it generates code to (optionally reflect) and invoke a method
it doesn't point to any real thing that you can use as an arg or put in a collection
Yeah that makes sense, and this isn’t even a static method
you can succinctly make a function that calls a method via memfn: (memfn someJavaMethod)
- this is first class, can be used with apply or map etc.
But will reflect
when I load open the project I'm interactively developing in emacs/cider, I have to open all the clj files that contain functions I call in my main 'runner' file and eval them to avoid class not found errors... what am I doing wrong?
Oh interesting, didn’t know about memfn
@macrobartfast did you load the main runner file? cider-load-buffer
(C-c C-k) by default
I did load the main runner file with C-c C-k without incident but still having to go load all the namespaces mentioned.
using lein repl, and cider-connect, if it matters.
you need to require the namespaces that your runner accesses
as long as you access the function from the main runner properly, there's no need to be in that ns
i'm wondering if there is some confusion that those deps required by the main runner are "visible" in that namespace but not visible from the current ns. Its hard to tell if this is a bug or users error
that should either error (if they can't be found) or guarantee they are loaded
I believe I did those things, but I'll do it all from scratch to double check everything; stand by (and thanks!).
@dpsutton @noisesmith lesson learned, and never forgotten. I was missing the parent directory in src with the project name; my clj files were directly in src for some reason; everything evaluates now.
(map #(foo % baz) bars)
vs (map foo bars (repeat baz))
PSA: Slack supports syntax highlighting for Clojure(Script) if you use the code snippet function over the code blocks. Makes your code easier to read here!
(map fn coll)
Not the same as GitHub’s
Oh you mean by clicking the “+” icon
Yeah but that’s a pain
It's actually less work than typing out the backticks...and it's also a pain to read a bunch of lisp code with no syntax highlighting, especially when someone is asking for help on it.
At least for small things
Naturally, for a single line of code that wouldn't be necessary.
Yeah I wanted it to work that way too @noisesmith