Annotating Function that Uses .. Macro

39 views
Skip to first unread message

Cristian Esquivias

unread,
Mar 2, 2014, 3:50:21 AM3/2/14
to clojure-c...@googlegroups.com
I'm just getting started with core.typed, picked a short function but can't figure out how to annotate it. I have:

(defn class-name [cls]
  (.. cls getName (replace \. \/)))

I added (ann [Class -> String]) but I get the error:

Unresolved instance method invocation replace.
Hint: add type hints.
in: (.replace (. cls getName) (quote \.) (quote \/))


I've tried every which way to add ann-form into the body (wrapping the entire call, wrapping only replace call, expanding the macro and wrapping the .replace call) but nothing seems to work.

Is there a way to annotate this function declaration?

- Cristian

Di Xu

unread,
Mar 2, 2014, 5:39:36 AM3/2/14
to clojure-c...@googlegroups.com
Hi, Cristian

from the error message, you should change your code into:

(t/ann class-name [Class -> (U String nil)])
(defn class-name [^Class cls]
  (.. cls getName (replace \. \/)))

this is caused by java interop, not by macro. core.typed will do type check after macro fully expanded. When encountered java interop, typed clojure requires class hint to do type inference.

Di Xu

unread,
Mar 2, 2014, 5:49:21 AM3/2/14
to clojure-c...@googlegroups.com
BTW, I'm not sure if `Class.getName()` and `String.replace()` will return `null` or not, if they won't return `null` in any cases, you could change it into:

(t/non-nil-return java.lang.Class/getName :all)
(t/non-nil-return java.lang.String/replace :all)
(t/ann class-name [Class -> String])
(defn class-name [^Class cls]
  (.. cls getName (replace \. \/)))

Cristian

unread,
Mar 2, 2014, 2:34:21 PM3/2/14
to clojure-c...@googlegroups.com
Hi Di,

Thanks for the help; both worked well.

One other question:

I like the second suggestion (using non-nil-return) so I went with
that. When I wrote (non-nil-return String/replace :all) I got an error
suggesting I use non-nil-return on String, but when I wrote
(non-nil-return java.lang.String/replace :all) everything worked. The
type checker never complains if I reference Class or java.lang.Class.

When do I have to fully reference classes? Is there a way to say
(non-nil-return String/replace :all) with getting an error?

Thanks,
Cristian
--
"We must not believe the many, who say that only the free people ought
to be educated, but we should rather believe the philosophers who say
that only the educated are free." - Epictetus

Di Xu

unread,
Mar 2, 2014, 7:57:20 PM3/2/14
to clojure-c...@googlegroups.com
eh, interesting..

From the error message, it seems that core.typed didn't treat argument in non-nil-return very smartly, from documentation in non-nil-return, we must provide it with "fully qualified method msym".

for Class case, I think core.typed annotate it internally, because it works when deleted (t/non-nil-return java.lang.Class/getName :all)
Reply all
Reply to author
Forward
0 new messages