Fork me on GitHub
#clojure-dev
<
2020-10-10
>
carocad18:10:22

hello everyone, quick question. As I was working on the grammar definition of Clojure’s symbols and keywords for my project (parcera) I received this report about symbols being allowed to have more than one / character. Although I have seen this for keywords I didnt think it was possible for symbols. Is this a bug? or is it also “tolerated” for backwards compatibility :thinking_face: • here is the example code: https://github.com/VladimirMarkovic86/ocr-lib/blob/master/src/clj/ocr_lib/core.clj#L13 • here is the report and reproduction case: https://github.com/carocad/parcera/pull/94#issuecomment-706546263

dominicm18:10:47

Just a thought: clojure.core// :)

carocad19:10:39

yep I am aware of that one. However in that case the namespace/simple-name still applies. The problem is something like foo/bar/baz . Which part is the namespace and which the name?

carocad19:10:19

just to be clear, I am talking about a literal simbol, not one made with (symbol ns name) 😉

dominicm19:10:26

> '/' has special meaning, it can be used once in the middle of a symbol to separate the namespace from the name, e.g. my-namespace/foo. '/' by itself names the division function. Troll answer: whichever one is nearest the middle :D

😅 3
dominicm19:10:54

user=> (re-matches symbolPat "clojure.core//")
["clojure.core//" "clojure.core/" "/"]
user=> (re-matches symbolPat "clojure.core/foo")
["clojure.core/foo" "clojure.core/" "foo"]
user=> (re-matches symbolPat "clojure.core/foo/bar")
["clojure.core/foo/bar" "clojure.core/foo/" "bar"]
user=> 
I'm sure you tried this, but the source regex is quite useful actually. Explains why // works

carocad19:10:26

I actually didnt try that 😅 . Good to know. However that regex could be seen as “an implementation detail”. In parcera I dont use them anymore because the LispReader has a lot of other checks for most tokens

dominicm19:10:59

different behavior

hiredman19:10:13

That code in ocr-lib is nonsense

dominicm19:10:53

Oh wow, I'm surprised that works…

user=> (import '[java.util Base64])
java.util.Base64
user=> (Base64/Decoder/getDecoder)
#object[java.util.Base64$Decoder 0x1237e0be "java.util.Base64$Decoder@1237e0be"]
user=> 
Gonna have to poke at how that resolves

carocad19:10:35

I did poke around but didnt understand it. Decoder is a public static class inside Base64 class. However, Decoder doesnt have a getDecoder static method. Only Base64 has :man-shrugging::skin-tone-4:

dominicm19:10:57

So this should really be Base64$Decoder/getDecoder I guess?

dominicm19:10:19

Oh, no. I see what you mean

dominicm19:10:22

Is the Decoder just ignored then?

dominicm19:10:44

Lol, yes:

user=> (Base64/flibbetygibbit/getDecoder)
#object[java.util.Base64$Decoder 0x1d25c1c "java.util.Base64$Decoder@1d25c1c"]
user=> 

carocad19:10:03

oh I didnt try that 😆

dominicm19:10:28

OK, figured it out I think:

user=> (Base64/flibbetygibbit/getDecoder)
sym: flibbetygibbit/getDecoder (flibbetygibbit / getDecoder)
From (flibbetygibbit/getDecoder)
Form: (. Base64 flibbetygibbit/getDecoder)
methodName: getDecoder

dominicm19:10:53

It's ignored by Clojure because clojure gets the name of the symbol, because it basically just wants a string

dominicm20:10:03

So by coincidence, it ignores the namespace in this form

dominicm19:10:21

Hmm, annoyingly it seems that Clojure actually behaves differently in the reader and clojure.lang.Symbol.

andy.fingerhut20:10:08

It appears you can use full name java.util.Base64$Decoder to name that Java class, but there doesn't seem to be a shorter way to refer to it, no matter what import statements you use.

andy.fingerhut20:10:20

But strangely enough, you cannot use the full name to refer to the getDecoder method in that class. Maybe I misunderstand the JVM docs for that class, though.

andy.fingerhut20:10:01

Doh. the getDecoder method is a method of class java.util.Base64. I think it makes more sense to me now.

dpsutton20:10:56

helpful information from alex the other day about this

dominicm20:10:03

@andy.fingerhut fwiw, the Decoder is completely ignored :) (Base64/foobarbaz/getDecoder) works just as well. It should be (Base64/getDecoder). It works because it expands to (. Base64 foobarbaz/getDecoder) and the Compiler uses the name of the symbol at the 3rd position.