Fork me on GitHub
#clojure
<
2022-06-14
>
jeroenvandijk07:06:41

I think i’m missing something here (in repl):

``````(/ 1.0 0.0) ;=> ##Inf

(def divide /)
(divide 1.0 0.0) ;=> ArithmeticException Divide by zero``````
What’s the difference?

2
teodorlu07:06:26

That's really weird

1
lassemaatta07:06:42

perhaps it has something to do with inlining?

✔️ 1
lsenjov07:06:52

That would be my guess too, but I've no idea how inlining actually works to test it

jeroenvandijk07:06:54

Can imagine it’s something like that

``````((fn [x] (/ 1.0 x)) 0.0) ;=> ##Inf

((fn [x] (divide 1.0 x)) 0.0) ;=> ArithmeticException Divide by zero
((partial / 1.0) 0.0) ;=> ArithmeticException Divide by zero
((comp /) 1.0 0.0) ;=> ArithmeticException Divide by zero
((identity /) 1.0 0.0) ;=> ArithmeticException Divide by zero

(eval '(/ 1.0 0.0)) ;=> ##Inf``````

lsenjov07:06:44

``````=> (ns clojure.core)
nil
=> ((nary-inline 'divide) 1.0 0.0)
(. clojure.lang.Numbers (divide 1.0 0.0))
=> (. clojure.lang.Numbers (divide 1.0 0.0))
##Inf``````

lsenjov07:06:54

That's how the inlining works, but doesn't explain why it's failing on the second case

p-himik07:06:04

The inlined version divides double primitives. The not inlined version divides Double objects.

1
✔️ 1
1
p-himik07:06:44

The primitive version just does `x / y` in Java, which results in `##Inf`. The Double version does an explicit check.

2
🍰 1
p-himik07:06:01

A funny thing:

``````(def x 1.0)
=> #'user/x
(def y 0.0)
=> #'user/y
(/ 1.0 y)
=> ##Inf
(/ x y)
Execution error (ArithmeticException) at user/eval5664 (form-init10727573377274659587.clj:1).
Divide by zero``````
Because there's a separate `Numbers/divide(double, Object)`:
``````static public double divide(double x, Object y){
return x / ((Number)y).doubleValue();  // <- returns a primitive as well
}``````

😎 2
M J07:06:29

Hi, I am a beginner to Clojure, and am trying to set up my team's project on IntelliJ. Its running for them, but for me I am encountering a Java error, and we haven't been able to fix it. I would appreciate any help. This is the error I am getting when doing "lein run": Compiling 2 source files to C:\Projects\strive_clojure\target\default\classes C:\Projects\strive_clojure\java_src\firebase\FirebaseAdmin.java:17: error: cannot find symbol var options = new FirebaseOptions.Builder() ^ symbol: class var location: class FirebaseAdmin C:\Projects\strive_clojure\java_src\firebase\FirebaseAdmin.java:33: error: cannot find symbol var builder = ActionCodeSettings.builder(); ^ symbol: class var location: class FirebaseAdmin Note: C:\Projects\strive_clojure\java_src\firebase\FirebaseAdmin.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. 2 errors Compilation of Java sources(lein javac) failed. Java Version is: java 17.0.2 2022-01-18 LTS Java(TM) SE Runtime Environment (build 17.0.2+8-LTS-86) Java HotSpot(TM) 64-Bit Server VM (build 17.0.2+8-LTS-86, mixed mode, sharing)

M J07:06:12

And any other "Hello World" project runs smoothly...

p-himik07:06:39

Make sure that the Java version that Lein uses is indeed 17 and not, say, 8.

p-himik07:06:29

You can check it by running `lein --version`.

M J07:06:34

I ran "lein --version": Leiningen 2.9.8 on Java 17.0.2 Java HotSpot(TM) 64-Bit Server VM

p-himik07:06:56

Hm, weird. But still - Java not recognizing `var` is a symptom of an old version being used, AFAICT. Maybe `lein` has some additional Java selection mechanisms inside it.

p-himik07:06:44

Note how the error mentions `lein javac`. Maybe you have `javac` on the `PATH` from an old JDK, somehow.

M J09:06:10

I fixed it. It somehow was depending on an old version of Java even though it showed Java17.0.2

M J09:06:22

Only deleting the old version made it work

genRaiy12:06:06

Is the person that owns the clojure-docs web site (https://github.com/zk) on here?

genRaiy14:06:38

lol - it was too short for my filter

Noah Bogart15:06:21

sadly, I don't think he checks very often, as I messaged him a couple months ago and he never responded.

genRaiy20:06:05

I'll open up a github issue to ask him on to the podcast in that case ;-)

Noah Bogart15:06:20

style question: my job has `parse-X` functions that overlap with the new clojure 1.11 functions. I'm trying to prepare us to move to 1.11, so that means handling the differences between our functions and the new ones. Our functions look like this:

``````(defn parse-long [x]
(cond (not x) nil
(integer? x) x
(and (string? x) (re-matches #"^\d+\$" x)) (Long/parseLong x)
:else nil))``````
This is significantly more permissive than the new functions (and we sadly rely deeply on the functionality), so I'm hoping to rename these to indicate they're more permissive. Any suggestions on names?

Alex Miller (Clojure team)15:06:58

Of course, you don't have to rename - you can just exclude core’s functions if you like

Alex Miller (Clojure team)15:06:50

But I read the function as more coercion than parsing

Alex Miller (Clojure team)15:06:04

So coerce-long, to-long, ->long seem like options

👍 3
Noah Bogart15:06:52

we would have to exclude them in every namespace they're used, right? I'm trying to avoid that kind of busywork

Noah Bogart15:06:01

those names are great, thanks

Joshua Suskalo16:06:22

The only thing to be careful with if you rename all your company-specific ones to `ensure-X` is that people are used to calling `parse-X`, so make sure you catch those in code review for the next while and try to educate your team on the change.

Joshua Suskalo16:06:02

Honestly might be worthwhile to exclude the clojure core ones for a while just so that it ends up as a compile error rather than a bug.

Noah Bogart16:06:20

That's a good point. I'm currently handling that by doing this in stages, where I'm changing all of the function names now, and then once this is merged and in use for a week or more, I'm gonna update to clojure 1.11, so in that middle period we'll catch anyone making mistakes. Might not be enough tho.

Joshua Suskalo16:06:32

sounds like a good start

dvingo19:06:57

I'm trying to `(set! *print-namespace-maps* false)` during repl initialization - I put it in `user.clj` when I start the REPL I get:

``Caused by: java.lang.IllegalStateException: Can't change/establish root binding of: *print-namespace-maps* with set``
where is the best place to put this so all my REPLs have this binding?

dvingo19:06:08

thanks Eugene 🙂

danieroux19:06:57

I have this snippet in user.clj:

danieroux19:06:01

``````(defmethod print-method clojure.lang.IPersistentMap [m, ^java.io.Writer w]
"From "
(#'clojure.core/print-meta m w)
(#'clojure.core/print-map m #'clojure.core/pr-on w))``````

dvingo23:06:57

this is awesome, thanks @U9E8C7QRJ

dpsutton21:06:31

I’m typing up an issue where we had relied on a message from `(.getMessage e)` from exceptions. I couldn’t reproduce a bug because java 14+ have nicer NPE messages vs no message in earlier versions. Does anyone know how to get a list (comprehensive or not) of standard java exception classes that do not have messages?

jumar09:06:54

Whether they have a message or not depends on how they are invoked right? You mean the cases when JDK itself throws these exceptions internally with no message?

jumar09:06:36

My naive search to get some esoteric ones, using ripgrep in JDK git repo

``````cd jdk/src/java.base

rg --files-with-matches 'class .* extends [a-zA-Z0-9]*Exception' | xargs rg --files-without-match 'super' | xargs rg --files-without-match 'getMessage\('

share/classes/java/util/IllegalFormatException.java
share/classes/java/util/EmptyStackException.java
share/classes/java/io/OptionalDataException.java
share/classes/java/util/FormatterClosedException.java
share/classes/sun/reflect/annotation/TypeNotPresentExceptionProxy.java
share/classes/sun/reflect/generics/reflectiveObjects/NotImplementedException.java
share/classes/sun/reflect/annotation/AnnotationTypeMismatchExceptionProxy.java
share/classes/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java
share/classes/jdk/internal/org/objectweb/asm/tree/UnsupportedClassVersionException.java``````
This is from late 2021 JDK code. The thing is that it probably misses a lot of stuff because as I said it depends on how the exception is constructed. I'd specifically check https://stackoverflow.com/questions/58696093/when-does-jvm-start-to-omit-stack-traceshttps://stackoverflow.com/questions/58696093/when-does-jvm-start-to-omit-stack-traces (for those Hotspot can optimize away their stacktrace if you don't use `-XX:-OmitStackTraceInFastThrow`) E.g. `ArrayIndexOutOfBoundsException`
``````rg 'throw new ArrayIndexOutOfBoundsException\(\)'

share/classes/java/io/ObjectInputStream.java
4107:                    throw new ArrayIndexOutOfBoundsException();

share/classes/jdk/internal/misc/Unsafe.java
1327:            throw new ArrayIndexOutOfBoundsException();
2424:            throw new ArrayIndexOutOfBoundsException(); ``````

dpsutton14:06:32

Yeah it was a fluke that the front end ignored the presence of a stack trace and some other info and solely checked for an error message. It's been corrected but I was just interested.

Joshua Suskalo14:06:00

Also isn't the message implementation-defined? I'd consider it dangerous to rely on because it could change depending on the java version or if you're using oracle jdk vs openjdk vs temurin vs graal

dpsutton14:06:15

Yeah I agree. It was an oversight. Fixed now. But I was wanting a list of error types that we were susceptible to on the jdk. But of course database drivers can throw errors with no message in some cases I'm sure

Joshua Suskalo14:06:05

Plus lots of user or library code that uses core java exception types. I know I use them myself quite frequently, and sometimes don't include messages if the error should be obvious from the type alone.

Alex Miller (Clojure team)21:06:15

NPE is the main one I'm aware of

🙏 1