Fork me on GitHub
#clojure
<
2023-04-17
>
Brian Beckman00:04:45

SOLVED (apologies if this should be in #beginners ) Hello — Looks like a Clojure int is a java.lang.Long for positive numbers, but not quite for negative ones. The smallest java.lang.Long is 0x8000000000000000, according to https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Long.java#L79, suggesting ordinary 64-bit twos complement:

jdk.internal.ValueBased
public final class Long extends Number
        implements Comparable<Long>, Constable, ConstantDesc {
    /** ... */
    @Native public static final long MIN_VALUE = 0x8000000000000000L;
    /** ... */
    @Native public static final long MAX_VALUE = 0x7fffffffffffffffL;
But Clojure seems to promote the hex literal for the smallest int to BigInt:
(format "0x%X" -9223372036854775808)
;; => "0x8000000000000000"
(class -9223372036854775808)
;; => java.lang.Long
(class 0x8000000000000000)
;; => clojure.lang.BigInt
How about the LARGEST negative number? Clojure format prints -1 as 0xFFFFFFFFFFFFFFFF, with 16 F’s, as expected for twos-complement:
(class -1)
;; => java.lang.Long
;; (format "0x%X" -1)
;; => "0xFFFFFFFFFFFFFFFF"
But Clojure seems to promote 0xFFFFFFFFFFFFFFFF to BigInt:
(class 0xFFFFFFFFFFFFFFFF)
;; => clojure.lang.BigInt
(= -1 0xFFFFFFFFFFFFFFFF)
;; => false
Something funny is going on. It’s not the top bit, either (as with many Lisps). With just the top bit off, Clojure (reasonably), thinks it’s got a positive Long:
0x4000000000000000
;; => 4611686018427387904
(format "0x%X" 4611686018427387904)
;; => "0x4000000000000000"
(class 0x4000000000000000)
;; => java.lang.Long
Is this just a reader issue with hex literals?

🏁 2
hiredman00:04:47

If the literal doesn't have a - in front in clojure it isn't a negative number

hiredman00:04:37

So 0x8... is not a negative number, and it doesn't fit in a positive long, so it is a bigint

hiredman00:04:34

You can wrap it in (unchecked-long ...) If you want to force interpreting the bit pattern as a long

🏁 2
Alex Miller (Clojure team)02:04:38

one other Java thing to be aware of is that there is a special case where Long/MIN_VALUE * -1 = Long/MIN_VALUE (due to overflow). "normal" Clojure multiplication with - checks and throws, but you can see this with unchecked-multiply:

user=> (* Long/MIN_VALUE -1)
Execution error (ArithmeticException) at java.lang.Math/multiplyExact (Math.java:949).
long overflow
user=> (unchecked-multiply Long/MIN_VALUE -1)
-9223372036854775808

👍 2
Ferdinand Beyer10:04:27

We encountered a surprising scenario recently: Delivered promises are affected by thread interrupts. I did search if that has already been discussed, but did not find anything. Apologies if I missed something. Here is some code to reproduce what I mean:

(def p (promise))
(def f (future
         (println "Future: Waiting for promise to be delivered.")
         (let [v @p]
           (println "Future: Got promise value:" v)
           ;; Something interrupts this thread; normally this would be another thread, maybe calling future-cancel.
           (.interrupt (Thread/currentThread))
           (println "Future: Interrupted.")
           (println "Future: Reading promise value again.")
           ;; This will not print, as @p will throw an InterruptedException.
           (println "Future: Promised value:" @p))))
(deliver p :hello)
@f ; => Execution error (InterruptedException) at java.util.concurrent.locks.AbstractQueuedSynchronizer/acquireSharedInterruptibly
In our case, this was surprising, since we deref the promise in a catch, but asserted before with a :pre condition that the promise is already delivered. I would argue that this is a bug, as dereferencing a delivered promise should not be considered a “blocking” call, right? Other promise implementations, e.g. Promesa using Java’s CompletableFuture, don’t throw InterruptedException in this scenario. What do you think?

Ferdinand Beyer10:04:00

This is a shorter example:

(let [p (promise)]
  (deliver p true)
  (.interrupt (Thread/currentThread))
  (deref p))

niwinz08:04:55

The main issue here I guess is the call to .await on the countdownlatch (on the clojure promise impl for deref), on CompletableFuture, the deref just calls get which returns immediately if promise is completed without any synchronization

👍 2
Ferdinand Beyer17:04:29

Yep, could probably be fixed by something like this:

clojure.lang.IDeref
(deref [_]
  (let [v* @v]
    (if (identical? v* d)
      (do (.await d) @v)
      v*))
Happy to provide a patch if this helps @U064X3EF3

Frank Henard14:04:38

I'm looking for a Clojure notebook (clerk, gorilla, etc.) that has good LaTex support. I think I saw that Gorilla supports it, but I also want to be up with the latest. The only notebooking I've done was with Jupyter with Clojure on the backend, but I want to be all in on Clojure apps if possible. Any recommendations?

genmeblog16:04:08

Clerk has KaTeX support (https://book.clerk.vision/#tex)

👍 2
jjttjj20:04:29

If I have a clojure source file with a bunch of symbols that were :refered in the ns form, is there a tool that can take a source code file and a map of namespace->alias pairs and replace all the referred symbols with the aliased symbol? I know I could probably do this manually with tools analyzer and rewrite-clj, but wondering if this exists yet So I want to do

(use-aliases "path/to/my-file.clj" {'medley.core 'm})
to replace in the source file calls like (map-vals ...) with (m/map-vals ...) (`map-vals` is a function in medley.core)

lilactown21:04:48

Clojure is missing a "codemods" repo with common stuff like this and utils to easily build them IMO

dpsutton23:04:26

I have a hazy memory that clojure.core.cache has a way to put a size limit on a cache? I can’t find any documentation why i think this but I thought i remembered core.cache having an example or some docs composing a ttl cache with a size bounded cache. does that ring any bells with anyone?

lread23:04:33

the memoize lib talks about https://github.com/clojure/core.memoize/blob/master/docs/TTL.md, maybe you are thinking of that?

dpsutton23:04:26

maybe that’s it. because i don’t see anything about size (in terms of mb, etc) from core cache

seancorfield23:04:38

fifo with a threshold is the size limited cache.

dpsutton23:04:57

aha. maybe that was it. i guess the notion of memory size was invented

seancorfield23:04:59

Oh, you mean memory, not number of elements?

dpsutton23:04:09

but yeah i think this was what i was thinking of. thanks @UE21H2HHD @U04V70XH6

phronmophobic23:04:48

You can also check out https://github.com/ben-manes/caffeine/ which has a bunch of useful features.

👍 2
☝️ 2
mpenet07:04:34

caffeine is a good bet, I think even datomic uses it internally, I suppose it has the rh stamp of approval