Fork me on GitHub
#clojure
<
2022-10-24
>
Matthew Twomey03:10:20

QQ: Are clojure instants always considered to be in UTC?

Alex Miller (Clojure team)04:10:18

Instants describe an instant in time, which is usually represented in UTC by default but can be represented in other time zones or offsets too (if you apply the right apis)

Matthew Twomey04:10:17

Thanks that is helpful. I note that an instant is represented in the repl as #inst "2022-10-24T03:28:10.110-00:00" I am theorizing that that trailing -00:00 will always be -00:00.

Matthew Twomey04:10:48

(when represented in “pure” instant form)

hiredman04:10:45

An instant literal is just a serialization format

hiredman04:10:39

The data that gets serialized that way could be in any number of formats

hiredman04:10:19

A common one is a java until Date, which is what instant literals deserialize to by default

hiredman04:10:32

The default serializers always serialize as utc, regardless of the time zone of the Date object

Martin Jul08:10:22

Adding to this, please note that (type #inst "2022-10-24T03:28:10.110-00:00") is java.util.Date - you probably want to use the improved java.time.Instant since its semantics are explicitly defined in terms of UTC-SLS per the docs @U064X3EF3 posted above.

👌 1
Alex Miller (Clojure team)12:10:27

Both should print as Clojure instants and respond true to inst?

Matthew Twomey14:10:40

Thanks @U064X3EF3 and thanks everyone for the very helpful pointers and background!

henrik09:10:31

(= (hash nil) (hash 0))
;; => true

;; But, no collision:
(assoc {} nil :value 0 :value)
;; => {nil :value, 0 :value}
Why is this? Is nil/0 handled explicitly in collection implementations?

p-himik09:10:40

That's how hash maps work. A hash function will inevitably produce collisions sooner or later, for all sorts of values of all sorts of types.

p-himik09:10:27

Wiki has a good description with informative diagrams on how hash collision resolution works: https://en.wikipedia.org/wiki/Hash_table#Collision_resolution

p-himik09:10:46

BTW, not that important, but in your example that resulting map's type is actually an array map - so hashes aren't used at all there.

henrik09:10:43

Right! It’s small enough. OK, I see. So basically the idea is: hash and hope that there’s no collision. If there is a collision, perform additional conflict resolution.

chrisn12:10:13

And for persistent hash maps, not array maps, nil keys are handled explicitly

👀 1
andy.fingerhut13:10:51

Clojure's hash-map implementation uses linked lists for all keys that happen to have the same hash function value, so performance can be bad if your application ends up colliding on hash keys a lot.

andy.fingerhut13:10:42

Clojure's hash function in version 1.6.0 was changed because the hash function for vectors and other collections collided more often than the Clojure developers wished, for certain commonly used sets of keys, e.g. 2-element and 3-element vectors of integers used as map keys.

henrik14:10:59

I was reading up on this, and the hashCode to hash with murmur3 move, which lead me to play around with the behaviour of hash. I get that it’s about minimizing the collisions now, not eliminating them. Incidentally, does this mean that = behaves in a way similar to hashed collection then? I.e., some kind of optimism based on hash, with more exotic stuff under certain circumstances.

andy.fingerhut15:10:47

@U06B8J0AJ I can imagine a performance optimization of = between collections that, if the hash functions of both collections were already computed (they might not have been -- they are computed on demand, not when the collection is first created), and they were different, then quickly return false from =. However, no such optimization would be (correctly) possible if the hash functions were the same.

andy.fingerhut15:10:10

Clojure's = does not implement such an optimization today, if I recall correctly.

andy.fingerhut15:10:33

= for many collections does quickly return false if their number of elements are different.

henrik06:10:08

Right, but I guess I should still consider = to be an O(n) operation for all intents and purposes then. I can see how this makes memoizing correctly, at the correct place and time, an artform.

Michael Gardner23:10:19

trivia: there used to be an infinite pessimization because of that shortcut: (= [] (range)) would never terminate, while (= (range) []) would return false. This appears to have been fixed in Clojure 1.11

👍 1
jean-lopes14:10:57

Hi, can someone help me understand why tap> has a different behavior (a.k.a. incomplete) on the first function in the following snippet: https://gist.github.com/jean-lopes/1968fc27dacb59eac8494c00f79daa7f

p-himik14:10:29

It works somewhat properly in my REPL - in a plain clj one. "Somewhat" only because the prompt for user's input appears in the middle of printing. But pprint is not atomic, so that's fine. So maybe the behavior that you see is caused by your particular REPL.

Alex Miller (Clojure team)14:10:33

almost certainly related to flushing in the output stream

p-himik14:10:21

Wouldn't subsequent prints then flush the previous ones? In the OP's example, the output is straight up missing.

Alex Miller (Clojure team)14:10:54

does this work better?

(defn tap-fn [x] (pprint x) (flush))

Alex Miller (Clojure team)14:10:23

just guessing... would be good to know what repl you're using too

jean-lopes14:10:52

the flush did not change the output. About the repl:

;; Connected to nREPL server - 
;; CIDER 1.4.0 (Kyiv), nREPL 1.0.0
;; Clojure 1.11.1, Java 17.0.4

Alex Miller (Clojure team)14:10:22

might want to ask in #C0617A8PQ or #C17JYSA3H - seems like I/O shenanigans

1
jean-lopes14:10:59

indeed, just tried on a repl open by "clj" and it has the desired output

Felipe Nascimento17:10:08

hey guys, Im trying call some java from clojure But I cant figure out how to call some lambda from clojure, it is a background job processing called jobrunr BackgroundJob.enqueue(() -> System.out.println("This is all you need for distributed jobs!"));

hiredman17:10:26

this has come up before, if I recall the enqueue method actually checks to make sure the class of the passed in object is marked as synthetic (which it is if generated by sam converting a lambda in java), but there is nothing in clojure that generates such a thing

Felipe Nascimento17:10:38

when I reifythe JobLambda Interface an error rise Please provide a lambda expression (e.g. BackgroundJob.enqueue(() -> myService.doWork()) instead of an actual implementation.

hiredman17:10:43

they want it to be a java lambda because of how they do bytecode inspection

Felipe Nascimento17:10:16

yeah, he end up using quartz and Im trying to run away from it.

Felipe Nascimento12:10:50

seans not to work

Felipe Nascimento12:10:58

(BackgroundJobRequest/enqueue
    (reify JobRequest
      (getJobRequestHandler [this]
        (println "test"))))
test
Execution error (NullPointerException) at org.jobrunr.jobs.JobDetails/<init> (JobDetails.java:27).
null

Felipe Nascimento19:01:00

update on this if anyone needed

(defn init []
    (doto
     (JobRunr/configure)
      (.useStorageProvider (new InMemoryStorageProvider))
      (.useBackgroundJobServer)
      (.useDashboard)
      (.initialize)))

(deftype LongJobRequestHandler []
  JobRequestHandler
  (run [this jobRequest]
    (println " Rodando Job..." jobRequest)
    (Thread/sleep (* 10 1000))))

(deftype
 LongJobRequest []
  JobRequest
  (getJobRequestHandler [this]
    LongJobRequestHandler))

(BackgroundJobRequest/enqueue
 (LongJobRequest.))

👀 4
richiardiandrea21:10:31

Hi all, is anybody using https://github.com/OWASP/java-html-sanitizer? Any thought around using it from Clojure?

hiredman21:10:09

not using it now, but we briefly had it as part of a service before html sanitizing became someone else's responsibility

👍 1
hiredman21:10:24

it's just another java library

lread21:10:19

Ya, I am using it https://github.com/cljdoc/cljdoc/blob/master/src/cljdoc/render/sanitize.clj. Happy to answer any questions you might have.

👍 1
lukasz21:10:47

We use JSoup, but our sanitizer is very aggressive and removes most of the markup, attributes and all styles

lukasz21:10:56

but good to know about this one!

Felipe Nascimento19:01:00

update on this if anyone needed

(defn init []
    (doto
     (JobRunr/configure)
      (.useStorageProvider (new InMemoryStorageProvider))
      (.useBackgroundJobServer)
      (.useDashboard)
      (.initialize)))

(deftype LongJobRequestHandler []
  JobRequestHandler
  (run [this jobRequest]
    (println " Rodando Job..." jobRequest)
    (Thread/sleep (* 10 1000))))

(deftype
 LongJobRequest []
  JobRequest
  (getJobRequestHandler [this]
    LongJobRequestHandler))

(BackgroundJobRequest/enqueue
 (LongJobRequest.))

👀 4