Adding type hints to returned IPersistentMap value

44 views
Skip to first unread message

cristian....@gmail.com

unread,
Mar 23, 2014, 3:13:24 AM3/23/14
to clojure-c...@googlegroups.com
I have a map of keywords as keys and java.lang.Class objects as values. When trying to annotate a function like:

(t/ann get-name [(IPersistentMap Keyword Class) -> String]
(defn get-name [m]
  (.getName (:foo m))

I get errors:
Call to instance field getName requires type hints.
Type Checker: Found 1 error

I try to add an ann-form around the "get" call, but it doesn't help. Is there a way to tell core.typed what the type of the value is?

In reality the map is a Record that's properly annotated and hasn't complained until I tried to add this function. So the function is more:

(t/ann get-name [MyRecord -> String])
(defn get-name [^MyRecord rec]
  (.getName (:class rec)))

but I get the same error.

Thanks for all the help,
Cristian

Ambrose Bonnaire-Sergeant

unread,
Mar 23, 2014, 3:17:18 AM3/23/14
to core.typed
It seems likely this has unresolved reflection.

Use (set! *warn-on-reflection* true) to find the culprit.

Thanks,
Ambrose

Ambrose Bonnaire-Sergeant

unread,
Mar 23, 2014, 3:19:10 AM3/23/14
to core.typed
I should probably add this to the hint, since this is by far the most common question.

Cristian Esquivias

unread,
Mar 23, 2014, 3:23:58 AM3/23/14
to clojure-c...@googlegroups.com
Hi Ambrose,

Thanks for the suggestion. I tried it out, but the only thing it complains about is that .getName can't be resolved (which I think is core.typed's issue as well).

The output:
Reflection warning, jina/play.clj:13:3 - reference to field getName can't be resolved.
Finished collecting jina.play
Collected 1 namespaces in 5257.36977 msecs
Reflection warning, jina/play.clj:13:3 - reference to field getName can't be resolved.
Start checking jina.play
8:  Not checking jina.play/->MyRecord definition
Type Error (jina.play:13:3) Call to instance field getName requires type hints.

Type Checker: Found 1 error
Found errors
Subprocess failed


Here's my test code in its entirety.

(ns jina.play
  (:require [clojure.core.typed :as t])
  (:import [clojure.lang IMapEntry IPersistentMap Keyword Seqable]))

(set! *warn-on-reflection* true)

(t/ann-record MyRecord [foo :- Class])
(defrecord MyRecord [foo])

(t/non-nil-return java.lang.Class/getName :all)

(t/ann get-name [MyRecord -> String])
(defn get-name [^MyRecord d]
  (.getName (:foo d)))


Thanks,
Cristian

Cristian Esquivias

unread,
Mar 23, 2014, 3:25:39 AM3/23/14
to clojure-c...@googlegroups.com
Huh. Just on a whim, I tried adding ^Class before (:foo d). That seems to have done the trick.

I didn't know you could do that :)

Thanks for the suggestion,
Cristian

Ambrose Bonnaire-Sergeant

unread,
Mar 23, 2014, 3:25:58 AM3/23/14
to core.typed
Yes, that's exactly the problem. You probably need something like (.getName ^Class (:foo d)).

Ambrose Bonnaire-Sergeant

unread,
Mar 23, 2014, 3:26:48 AM3/23/14
to core.typed
If it wasn't clear, unresolved reflection is a type error in core.typed, even if the types match up perfectly.

Thanks,
Ambrose
Reply all
Reply to author
Forward
0 new messages