This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-26
Channels
- # adventofcode (12)
- # beginners (141)
- # cider (3)
- # cljsrn (3)
- # clojure (76)
- # clojure-russia (1)
- # clojure-spec (7)
- # clojure-uk (4)
- # clojurescript (15)
- # css (1)
- # duct (3)
- # emacs (5)
- # fulcro (85)
- # keechma (1)
- # leiningen (44)
- # off-topic (29)
- # om (6)
- # parinfer (4)
- # perun (1)
- # re-frame (18)
- # reagent (2)
- # ring-swagger (8)
- # shadow-cljs (5)
- # spacemacs (1)
- # sql (7)
Hi all, I'm trying to populate a java array with values from a clojure seq and it seems super slow. e.g.
(time (def my-seq (take (Math/pow 10 6) (repeatedly #(rand)))))
runs in under 1 ms, while
(time (def my-arr (double-array my-seq)))
takes more than 150 ms
What am I doing wrong?
the first one, you aren't measuring anything meaningful
take and repeatedly are both lazy, and you don't force the value inside the timing
so the second thing you time is really the time usage of both together
try putting doall
around take - also repeatedly takes an optional number of repeats argument and #(rand)
is identical to rand
so you can replace the first one with (time (def my-seq (doall (repeatedly (Math/pow 10 6) rand))))
For one of my first projects, I made a command-line runner for the 4clojure problems: https://github.com/porkostomus/ctrain
I want someone to be able to pass a string or a BufferedImage object and have this function do the right thing
@slack1478 yes, multimethods and protocols are the two easiest ways to do this in clojure
multimethods are better in your case unless you are doing this for performance
this helped though https://www.braveclojure.com/multimethods-records-protocols/
if examples help there’s also this https://clojuredocs.org/clojure.core/defmulti
(defmulti bake (fn [image-or-file & params] (class image-or-file)))
(defmethod bake IIOImage [image filename metadata]
(write-image filename
(reduce set-metadata image metadata)))
(defmethod bake String [input-filename filename metadata]
(let [image (load-image input-filename)
metadata (conj (metadata input-filename))]
(bake image filename metadata)))
you either need to use import in that ns to use it without qualification, or use it by its fully package qualified name
are you sure you have the package right?
problem is the ClassNotFoundError doesn't point me towards any helpful line, just URLClassLoader
this is a class loading problem, printlns won’t help
the most likely thing is subtly getting the package name wrong
copied straight from https://docs.oracle.com/javase/8/docs/api/javax/imageio/IIOImage.html
no, it comes with your jvm
I don’t know how you’d get class not found for that unless there was a typo somewhere honestly (or a headless vm but you use the class elsewhere in the code without problem so…)
heres the full context https://docs.oracle.com/javase/8/docs/api/javax/imageio/IIOImage.html
@slack1478 I just checkout out your repo, looks fine?
justin@justin: ~/metapng$ git checkout multimethod
Branch multimethod set up to track remote branch multimethod from origin.
Switched to a new branch 'multimethod'
justin@justin: ~/metapng$ clj
Clojure 1.9.0
(ins)user=> (doto 'metapng.core require in-ns)
metapng.core
metapng.core=>
I’d expect that to act the same
same result - just leaves me in the user ns
did you reload the code without restarting your repl?
might be a caching bug with the clj tool
it would be cool to replicate the caching issue and submit a bug report to the clj team- but since this is #beginners just knowing we sorted it might be enough
and it is most definitely a caching issue because its printing out lines where I have 0 printlns in my code
not only is clj replacing a subset of leiningen’s funcitonality, it’s recreating a subset of past leiningen bugs :P
since caching issues already came up, another thing to pay attention to when using multimethods is that when you reload your code the multimethod isn’t redefined - if you need to happen you need to explicitly remove it ((def mymulti nil) is the easiest way to do that)
does it make sense to restat clj every time i get an error with my source file in (use 'calendar)
or something like that
you can use load-file
or add the optional :reload
arg to require
I find that use
is useful for my custom user
namespace definition, and clojure.repl
and clojure.pprint
and otherwise (and especially for code that I am actively developing) require with an alias and/or switching to that namespace in the repl is more productive
but if you are in ns foo.bar
you can still run (require 'foo.bar :reload)
and it will work (with caveats about how some constructs reload of course - but generally it works)
when you use
the ns, you might need to run use
again after loading more definitions though - the mapping is done to your current ns at the time use is called, so it won’t see future definitions and map them
can i use override-deps to point to a local/root even if my regular deps shows a mvn/version?
load-file works regardless of where you initially got the dep
but the rest only really work with the current project, or if you are using lein checkouts
(of course you need a file on disk to use load-file but I assume that’s the case if you are editing it)
not using load file, using deps.edn and clj -R:dev
with :aliases {:dev {:override-deps {metapng {:local-root "/my/dev/dir/metapng"}}}}
usually the way people do this is they have a keystroke in their editor. the editor is connected to the repl and calls load-file
behind the scenes
what I’m saying is load-file will work for loading file changes
and I don’t know enough about clj to tell you if it can make require work - but the easier path is to use load-file which is guaranteed to work
I wonder if there’s a #clj channel yet for that tool (looks like no)
so I tried (load-file "/path/to/metapng/core.clj") then
(require 'calendar :reload)` but it seems to be using the installed maven version, not my local one TT
the :reload caused require to undo the changes load-file did - anyway it’s one or the other, there’s never a reason to use both in a row for the same ns
also - what is this “calendar” - is it a single segment namespace? surely it’s not a namespace defined in metapng/core.clj - what are you actually doing here, where does this “calendar” come from?
there’s a few problems with single segment namespaces - but if it’s just something you only use from a source file in the current project that should be fine
also .core
is based on leiningen not knowing enough about your project to come up with a better name and isn’t needed - you can give your namespace any name you like
well, metapng really only has 2 functions it should expose, and honestly I would like people to add it via something like [jedahan/metapng :as metapng]
the / version isn’t valid
and imho jedahan.metapng is a much better ns than metapng.core
yeah, deps are for artifacts, require is for things provided by those artifacts - it’s too bad they look so similar because they are very different things
given current conventions, if anyone else decided “metapng” would be a good name for a thing, the likelyhood that metapng.core would clash is high
so like, deps for pngj is ar.com.hjg/pngj
, but I import it via ar.com.hjg.pngj
, I don't understand
one is a maven group and artifact name, separated by a slash, the other is a package which has some classes in it which could be in any artifact
so deps of jedahan/metapng
with import jedahan.metapng :as metapng
I think reads nicely
yes, that is intuitive, and avoids conflicts in a way that metapng.core doesn’t
import never allows :as so I assumed you meant require :)
so then, can i have jedahan.metapng.tests
and is there a way to make jedahan.metapng functions private (with defn-) but visible/testable to the tests?
you can use @#’foo to call a private var called foo
"private" in Clojure is much like "private" in Groovy -- somewhat advisory 🙂
breaking it down - #’foo returns the var for foo, and @ extracts the contents of that var (deref)
so it’s a low level workaround skipping the check for privateness that the clojure compiler would do if you used the name directly
(and you only need @
for Vars -- with def ^:private
-- for functions you can omit @
and Clojure will automatically dereference the Var for you)
that’s true - I had forgotten whether #' quote of vars alone was enough to avoid the privacy check and included @ to be safe - turns out it’s not needed
My recommendation is to think very carefully about whether you really want a function to be private. If it has testable behavior, it probably has useful behavior and might as well be public and part of your API.
An alternative is to put "implementation details" in a .impl
namespace (and leave them public).
That makes the implementation easy to test and clearly separates implementation functions from the public API as well.
bonus points if you give the namespace a cumbersome name and / or use some trick like implementing everything in terms of protocols so that people have to use reify or deftype or defrecord to use any of it, sure to keep the riffraff out (no, don’t actually do this, this is just a joke)
What's the idiomatic way to return true
if any of a sequence of bools is true
? reduce
with or
does not work since or
is a macro (which makes sense given the desirability of short-circuiting its evaluation).
I ran in to a similar problem yesterday where I could not use if
directly in a datascript query, for the same reason.
Perhaps there are non-short circuited versions of the logical operations somewhere?
It would seem to make more sense though to have a short-circuting reduce
though
I am assuming there is something more idiomatic out there than (defn aor [x y] (or x y))
...
(partial some? true?)
depends on your taste for partial
and of course I meant (partial some true?)
😛
the way I would do it with reduce: (reduce #(when (true? %2) (reduced true)) false coll)
but yeah, use some
for that
Ah, some
is what I was looking for! (some identity x)
does exactly what I wanted. Thank you, @jgh @donaldball @noisesmith!
also you mention short circuiting above - to be clear, reduced
causes reduce to short-circuit with the value provided