This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-05-01
Channels
- # announcements (3)
- # babashka (17)
- # beginners (163)
- # bristol-clojurians (1)
- # calva (18)
- # chlorine-clover (17)
- # clj-kondo (13)
- # cljs-dev (50)
- # cljsjs (3)
- # cljsrn (13)
- # clojure (218)
- # clojure-dev (5)
- # clojure-europe (9)
- # clojure-italy (10)
- # clojure-nl (8)
- # clojure-uk (107)
- # clojurescript (25)
- # conjure (163)
- # cursive (63)
- # data-science (9)
- # datomic (38)
- # docker (1)
- # figwheel (34)
- # figwheel-main (3)
- # fulcro (15)
- # graalvm (1)
- # helix (12)
- # jobs (3)
- # juxt (5)
- # kaocha (3)
- # lein-figwheel (2)
- # leiningen (6)
- # luminus (2)
- # malli (1)
- # meander (12)
- # nrepl (4)
- # rdf (2)
- # re-frame (2)
- # reagent (7)
- # reitit (5)
- # remote-jobs (2)
- # rum (1)
- # shadow-cljs (65)
- # spacemacs (27)
- # tools-deps (18)
- # vim (19)
- # xtdb (2)
Question to date and time data: is clj-time still the recommended lib for this? There's conflicting information on the interwebs about what to use. Apparently Java has improved a lot and it's now recommended to use java.time directly?
I'm one of the maintainers of clj-time: please don't use it -- either use Java Time directly via interop, or one of the wrappers recommended in the clj-time readme.
https://github.com/dm3/clojure.java-time or https://github.com/henryw374/cljc.java-time or https://github.com/juxt/tick
lol, you need to make that note at the top even bolder and bigger Sean 😛 and red! maybe some <blink>
@seancorfield thanks. I'll look into clojure.java-time then. I assume I can extract day, month, year etc from a value?
I'll change the wording from "consider using" to "please use" perhaps.
@bfabry yeah - perhaps in RED 🙂. Stackoverflow is full with old answers from 7 years ago. nothing new though.
ah yes SO is particularly vulnerable to bit-rot. once that answer is ticked as accepted it probably will never change
Yeah, a lot of tutorials out there refer to clj-time -- I really don't know why it was so popular. Joda Time was already an immutable, value-based time library. clj-time really only adds a bit of syntactic sugar.
@seancorfield Thanks for the help. I now can parse "2020-0430T20:27:56Z" :_)
why does the first expression works but not the second? (= 2020 (t/as (t/zoned-date-time "2020-04-30T20:29:00Z") :year)) (= (list 2020 4) (t/as (t/zoned-date-time "2020-04-30T20:29:00Z") :year :day-of-month))
What is t
?
Day of month is 30, not 4.
user=> (t/as (t/zoned-date-time "2020-04-30T20:29:00Z") :year :month-of-year :day-of-month)
(2020 4 30)
user=>
I'd like to filter all datetime value of a specific date. I thought I'd extract year, month and day and then compare two lists, no?
Using Java Time directly is just as easy:
user=> (def year-month (juxt #(.getYear %) #(.getMonthValue %)))
#'user/year-month
user=> (year-month (java.time.ZonedDateTime/parse "2020-04-30T20:27:56Z"))
[2020 4]
user=>
Or if you want the day as well
user=> (def year-month-day (juxt #(.getYear %) #(.getMonthValue %) #(.getDayOfMonth %)))
#'user/year-month-day
user=> (year-month-day (java.time.ZonedDateTime/parse "2020-04-30T20:27:56Z"))
[2020 4 30]
user=>
There are plenty of good reasons for not bothering with a simple wrapper, and just using interop.
Unless you want to write platform-independent code, in which case cljc.java-time or juxt/tick could be used.
“platform-independent dates” https://knowyourmeme.com/memes/%E0%B2%A0_%E0%B2%A0-look-of-disapproval
Yeah, well, some people seem to think such code is worthwhile. I don't do cljs so I don't care 🙂
Now that I think about it, it’s odd that I feel that way. In theory, they’re like letters or numbers. Their properties are derived from real life. But, if we’re honest, I’m pretty sure dates are a damn mess in every ecosystem.
Even in a single ecosystem…. good lord java has 3 built-in competing date/time libs. And that doesn’t even include JodaTime!
they're not really "competing". but yeah time is hard. can't wait till we have to deal with vehicles that travel at an appreciable fraction of the speed of light someday (if it ever happens)
Oh I agree, dates are the worst. We've been doing Clojure for a decade and we started with date-clj
rather than struggling with Java since we were on Java 6 or Java 7 back then. We added clj-time
at some point and started migrating to that, but I think that just made things more complex. Since we moved to Java 8 we started using Java Time (and clojure.java-time
). We're on Java 11 right now and still have all three Clojure libraries in our code base 😐
I am slowly replacing the first two with the third (and, yes, using the clojure.java-time
wrapper a bit)... but we have nearly 100K lines of Clojure at this point so it's slow going...
It’s the sort of work that’s impossible to prioritize highly. Things somehow work, despite the inconsistencies. So, yeah, in small chunks over long periods of time is the only way to go.
@bfabry you have not seen what I have seen. If they’re not “competing,” I don’t even wanna know what the proper word is. I’m sure it’s absolutely filthy.
(and of course when you interact with JDBC, you tend to need java.util.Date
anyway)
They're both subtypes of java.util.Date
😛
I just love how java.sql.Date
extends java.util.Date
and then disables all the time stuff! 😢
@U0TSNMT53 it's always a good discussion to have -- I think a lot of devs don't realize what a mess it can be and how complex date/time stuff really is (esp. timezones).
We have all our servers set to UTC, our JVMs set to UTC, and our database set to UTC -- all to avoid timestamp complexities!
@seancorfield good man
well there is one you're supposed to use, and 3 others that have writing on their main webpages saying "don't use this". so that's what I mean by not "competing". They're certainly all "there" and "conflicting" and "annoying" 🙂
My fav is how, no matter how much I want to use java8 dates, I’m bound to use java.util.Date
by the clojure reader now.
You can change the data reader map to read tags however you want
The default type the reader uses for #inst tags is Java util date, but given a reader you control you can make it anything else
Reality is: I’m never gonna override #inst
. I might do a custom tag, but probably not that either. Because I have #inst
.
user=> (inst-ms (java.util.Date.))
1588296744460
user=> (.getTime (java.util.Date.))
1588296759500
user=>
Ah yes, just figured that out.
inst-ms ends up being a Rosetta Stone when you get a date, but are not sure what the exact type will be
Doesn’t it work on impls of the Inst protocol?
Hello, please what's wrong with (use '[ring.util])
? I want to import all functions from ring.util
use
brings along more than the functions in the namespace, it also brings the dependencies that the other namespace has. At some point you will get conflicts and it could be time consuming to resolve.
The require
with :as
or :refer
keeps your code very clean and specific in terms of what it pulls in to a namespace.
One theory is that topojson files are not working with Vega-lite, perhaps something about the topology they add. But I am still testing this idea
@U05254DQM I think that was meant for a different slack :)
@noisesmith Oh yes it was, unless you can help me find some GeoJSON files that work with Vega-lite and match up to the http://Gov.uk data 🙂
haha I''ll see what I can do
Next time you are at the Office of National Statistics, please ask them why there GeoJSON files dont work with vega 😂
It makes it harder to understand where a function is coming from. Is it clojure.core? Is it code in my current namespace? or is it use
d? So people tend to prefer to add an alias, so that its immediately obvious that its coming from somewhere else.
There are a few exceptions, clojure.test
is usually required refer’ing all (at least on JVM). And you also have the option to refer specific functions with require.
Hello, I’ve been stuck with this problem for a bit. Is the following possible? If so, could you please point me to the right direction? I’ve got a verbose function like:
(defn word2vec [{:keys [max-iter
step-size
window-size
max-sentence-length
num-partitions
seed
vector-size
min-count
input-col
output-col]
:or {max-iter 1,
step-size 0.025,
window-size 5,
max-sentence-length 1000,
num-partitions 1,
seed -1961189076,
vector-size 100,
min-count 5
input-col "sentence"
output-col "features"}}]
(-> (Word2Vec.)
(.setMaxIter max-iter)
(.setStepSize step-size)
(.setWindowSize window-size)
(.setMaxSentenceLength max-sentence-length)
(.setNumPartitions num-partitions)
(.setSeed seed)
(.setVectorSize vector-size)
(.setMinCount min-count)
(.setInputCol input-col)
(.setOutputCol output-col)))
The thing is that the method name is always just the camel-case version of the arg name, and each argument is repeated four times. I feel like it should be possible to write a macro such as:
(defstage word2vec
Word2Vec
{:input-col "sentence"
:output-col "features"
:max-iter 1,
:step-size 0.025,
:window-size 5,
:max-sentence-length 1000,
:num-partitions 1,
:seed -1961189076,
:vector-size 100,
:min-count 5})
I’m stuck in the part where I’m converting the key to the camelcase method - something like:
(defmacro set-param [spark-stage k v]
(let [method `(symbol (str "set" (->PascalCase (name ~k))))]
`(. ~spark-stage ~method ~v)))
(def stage (Word2Vec.))
(def k :max-iter)
(set-param stage k 5) ;; throws java.lang.IllegalArgumentException
but it obviously doesn’t work! Is this the wrong approach altogether?@seancorfield I rather stick to the Clojure wrapper as long as possible. I avoided Java for the recent 25 years and I'd like to keep it like that 🙂. Thank you for explaining the options though. I know that I have go out to Java anyway. When I started looking into Clojure I was a bit taken back by the attitude "it's better than Java here and better than Java there". I don't care about Java ;-).
hey everyone, trying to figure out what’s going on with my setup as follows:
(with-redefs-fn [sut/a (fn [& args] (prn "hi"))]
(sut/b "test!"))
where b
calls a
. however, when i run this, a has its original value, namely that before it was redef
’d. why isn’t it rebinding?yeah, if b creates a thread, with-redefs-fn needs to be forced to wait until b's thread finishes somehow (or you need something better than with-redefs-fn - eg. a dynamic binding wouldn't have this problem as they are shared with future threads and you can propagate them to other threads as needed)
i was looking at alter-var-root .. and then attempting to set it back afterwards (this is in a test)
@gtzogana you can use something similar to the cljs async
wrapper for tests - which makes sure a form doesn't exit until a callback is called. You can make it yourself like this:
(let [done (promise)]
(with-redefs-fn [sut/a (fn [& args]
(deliver done true)
(prn "hi"))]
(sut/b "test!")
@done))
with-redefs-fn will not exit (and thus a will stay in place) until a tells it it's ok via done
if a needs to be called n times, you need a different place to deliver to done, or a conditional deliver, but the concept stays the same
there's still a gotcha: with-redefs-fn / with-redefs are able to lose your original binding permanently if used in two threads at once
do you mind explaining how this happens? i noticed it in the docs but it’s not quite clear what’s going on
so, (with-redefs [f g] (body)) does the following: • save the global binding of f as f-old • set the global binding of f to g • use a finally clause so that ensures no matter what, g is replaced with f-old
let's imagine two threads call with-redefs: • thread a calls (with-redefs [f g] (body)) • f is now g, a has f-old of f • thread b calls (with-redefs [f h] (body)) • f is now h, b has f-old of g • a exits, automatically setting f to f-old • b exits, automatically setting f to g • the original f no longer has any gc root, and the garbage collector deletes it permanently
so by calling with-redefs twice, you permanently lose the original value (if thread a exits before thread b, and their execution overlaps)
classic race condition
most test suites will never do this, but consider that this usage ensures your tests can't correctly be run concurrently
Hey, was hoping to get some help. I'm trying to use the react-particles-js library with a reagent/re-frame project, I can get it to display, but the interactivity/hover isn't working. Was wondering if there is something glaringly obvious I'd missed, pretty new to this. This is the element in question:
[:> Particles
{:particles {:number {:value 200
:density {:enable true
:value_area 1000}}}
;; This bit doesn't work:
:interactivity {:detect_on "canvas"
:events {:onhover {:enable true
:mode "repluse"}}}]
Thanks for your helpI also realise that this might be the wrong thread. Should I ask in the clojurescript thread instead?
I bet #clojurescript or #reagent is more likely to have your answer
What is :cljsrn I see in some cljc files on github? And how is that different from :cljs?
Hello, I have a question about Cursive and Clojure test. When I def
inside a deftest
the IDE says the variable cannot be resolved. How could I prevent this warning? Thanks.
hey @hammerha, I am pretty new, but I have never seen a def
defined in a defn
or deftest
@hammerha def is for making namespace scope definitions, if you want something to use inside ns-test use let
def there will work - sometimes - but it means every time the test runs the definition changes and all tests can see the definition, probably not what you were aiming for
(deftest ns-test (let [abc 1] (is (= ....)))
great, thanks a lot for the answer @patrick.farwick @noisesmith!
if I want to work with paths in a cross-platform manner in Clojure, what is roughly the equivalent of Node.js path
module?
pretty much every project I write has:
(defn path [s & ss]
(java.nio.file.Path/of s (into-array String ss)))
? 🙂 In response to path
? 🙂
in response to making functions to work with Path
Ah, yeah, the whole cross-platform file pathing nightmare...
seems like I spent most of this week converting between Files and Paths :)
And that sometimes on Windows you get c:\path\to\file.ext
and other times you get /c:/path/to/file.ext
🤯
yeah, it's a minefield
(I'd never seen the latter until recently)
Anecdote: My very first programming project on university (a board game) had a bug with file paths, leading it not to be able to load taunts.txt, which it considered fatal and therefore terminated. I think it was tripping on spaces or something, but yeah, not a very beginner friendly API :’)
Also, on Windows, some of the APIs treat certain filenames as reserved (try using con.clj
with the File
stuff 🙂 -- or prn.txt
, nul.jpg
, etc...)
oh yeah, they had special meaning in dos, right?
i’ve always just worked with
s directly via
. is there a reason to prefer Path?
Yup, see https://github.com/seancorfield/depstar/issues/8#issuecomment-489873152 which was the bug report against an early version of depstar
that had that problem!
there's a lot of interesting stuff in java.nio that depends on Path
I skimmed through the bug, but I can’t figure out how Path vs File figures in?
@U7RJTCH6J This article talks about the new-in-Java 7 nio
stuff https://www.oreilly.com/content/java7-features/ (starts halfway down).
the main thing that kind of blew mind a little is that java 7 has both glob and regex file path matching built in since Java 7
it's a pain in the ass to use well, admittedly
sorry to trigger you @U064X3EF3
no worries :)
I'm packaging a jar using uberjar, and getting this error when I run the resulting jar file
Exception in thread "main" java.lang.NoSuchMethodError: clojure.lang.Util.loadWithClass(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;
at inspect.core.<clinit>(Unknown Source)
When running
java -jar target/inspect.jar
has anyone got any ideas on how to debug?using the following steps:
mkdir classes
clj -e "(compile 'inspect.core)"
clojure -A:uberjar --main-class inspect.core
java -jar target/inspect.jar
Taken from https://github.com/tonsky/uberdeps#creating-an-executable-jaroh, you aren't using lein, deleting my message
ah yeah I should have written uberdeps not uberjar when explaining my problem
did you miss the step where you add classes to your paths?
my deps.edn looks like
{:paths ["src" "classes"]
:deps {org.eclipse.lsp4j/org.eclipse.lsp4j {:mvn/version "0.8.1"}
org.clojure/tools.nrepl {:mvn/version "0.2.13"}}
:aliases {:uberjar {:deps {uberdeps {:mvn/version "0.1.10"}}
:main-opts ["-m" "uberdeps.uberjar"]}}}
I've seen a couple of people with this issue https://www.google.com/search?q=NoSuchMethodError%3A+clojure.lang.Util.loadWithClass but didn't find any answers
I've found depstar
painless, it does what I want and even lets me use clojure.main as my entry point (pointing at my main ns) instead of having to aot compile
so it looks like you are compiling with one version, but what is getting packaged in the uberjar is another (older version)
yeah that looks like it's working thank you, I'll checkout depstar at some point too seems like less steps generally
I always get confused about when to add Clojure as a dependency in deps
ah ok my kinda rule
@sfyire If it helps in the future, if you use clj-new
to create new projects, they automatically have built-in aliases to create JAR or uberjar files, and know how to deploy to Clojars etc.
https://github.com/seancorfield/clj-new -- the app
and lib
projects it generates use (my fork of) depstar
to produce uberjars (with AOT compilation etc) and thin JARs respectively. They also have :test
and :runner
aliases to run your tests etc.
ah I didn't know clj-new did that, cool
@sfyire Feel free to hit me up via DM if you have any questions about clj-new
or depstar
-- or anything in my dot-clojure
repo (which is full of "interesting" stuff to add to your ~/.clojure/deps.edn
file 🙂 )