> Have you seen this?
> http://www.assembla.com/wiki/show/clojure/Enhanced_Primitive_Support
>
Indeed, though that's old. See http://dev.clojure.org/display/doc/Enhanced+Primitive+Support instead.
> I couldn't find a practical use of doing (defn ^String foo [] ...)
> what's hinting the fn name good for?
That's how one hints a non-primitive return type; that's been the case for a long time now.
> You don't mention ^:static and that seems to be required for best
> performance.
> :static
> •defn supports {:static true} metadata
> •:static fns can take/return longs and doubles in addition to Objects
> •compiler will compile static methods in addition to IFn virtual
> methods
^:static has been a no-op for a while AFAIK, made unnecessary after changes to vars a while back.
> The metadata isn't there, so I guess some symbol table is involved in
> compiling static functions, not just the var.
The compiler relies upon a stack of interfaces that define primitive-hinted function invocation:
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/IFn.java#L91
I haven't investigated the details sufficiently enough to comment beyond that.
- Chas
Of course, this isn't how 1.3.0 alphas work now, but unless things are really locked down, I hope the above is a reasonable starting point for discussing how to smooth out the inconsistencies that currently exist.
What do you get from (map meta (:arglists (meta #'foo)))?
(defn foo^String ([] "bar")^double ([a] 5.6)([a b] :not-hinted-at-all))
I can see the inconsistency but for multiple arity/body functions
that's not a bad place to put it. My suggestion would be to extend
(declare) à la maclisp and keep the actual fn clean of hints (at least
the signature).
http://bitsavers.trailing-edge.com/pdf/mit/ai/aim/AIM-421.pdf
=> (->> #'foo
meta
:arglists
(map (juxt identity meta)))
([[] nil] [[a] {:tag long}] [[a b] {:tag double}])
Beautiful. I clearly wasn't clever enough to spelunk deeply enough into the metadataÎ. Thank you, Ken.
I'd hope that the [] arity could get a :tag of java.lang.String, but that may be running into semantic difficulties as David is potentially pointing out separately.
Thanks again,
- Chas
(defn ^String foo [])(defn foo ^long [])
??
Using 1.2:
sandbox=> (defn bar [] "foo")
#'sandbox/bar
sandbox=> (defn foo [] (.length (bar)))
#'sandbox/foo
Reflection warning, NO_SOURCE_PATH:1 - reference to field length can't
be resolved.
sandbox=> (defn ^String baz [] "foo")
#'sandbox/baz
sandbox=> (defn foo [] (.length (baz)))
#'sandbox/foo
Looks like it recognizes it as hinting the return type to me.
What? Please actually respond in English, rather than by pointing
mutely at something whose salience is not even apparent.
>>>> The real problem is that first case was never actually specifying a
>>>> return
>>>> type - it is a type hint on the var that happened to store an fn. The fn
>>>> itself can only return Object (<=1.2.0).
>>>
>>> ??
>>>
>>> Using 1.2:
>>>
>>> sandbox=> (defn bar [] "foo")
>>> #'sandbox/bar
>>> sandbox=> (defn foo [] (.length (bar)))
>>> #'sandbox/foo
>>> Reflection warning, NO_SOURCE_PATH:1 - reference to field length can't
>>> be resolved.
>>> sandbox=> (defn ^String baz [] "foo")
>>> #'sandbox/baz
>>> sandbox=> (defn foo [] (.length (baz)))
>>> #'sandbox/foo
>>>
>>> Looks like it recognizes it as hinting the return type to me.
>>
>> https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L3236
>
> What? Please actually respond in English, rather than by pointing
> mutely at something whose salience is not even apparent.
What David is getting at is that Object-based hints (as we've had all along) don't impact the signature of the generated function's invoke method -- their return types are always Object, and the hint is "just" used to determine which cast to use when the function's return is used in an interop context (and only in interop contexts, since "regular" Clojure functions never have statically-typed arguments). In contrast, primitive type hints _do_ change the signature of the corresponding function's invoke* method via the selection of the appropriate IFn$NNNNN interface that has statically-typed arguments and return types.
What started this is I don't happen to think that's relevant re: syntax and the placement of the type hint — or, more to the point, that essentially no one does/will/should understand the difference in the implementation details and choices that are represented in the differentiated placement of the hint in:
(defn ^String foo [])
vs.
(defn foo ^long [])
- Chas
That's* different from his original claim that you "can't hint return
types", or words to that effect**; you can't enforce return types (as
in, returning the wrong type invariably throws CCE, or else it won't
compile), but you can hint them (and then wrong type used in interop
expression may cause CCE).
With 1.3, it looks like maybe you can enforce primitive return types
in some cases.
* If it even IS what he was getting at. All he posted was a URL, and I
don't think it's at all clear that that was what he meant by doing so.
And yes, that's after clicking through it and having a cursory look
around near the landing site in the code.
** To be exact, he said you can't "specify" return types, "it is a
type hint on the var that happened to store an fn". This reads to me
as implying that hinting (defn ^String foo [] ...) is hinting that foo
references a String rather than an IFn that returns a String, but the
compiler sure seems to interpret foo as referencing an IFn that
returns a String. :)
MORE type hinting inconsistencies, then.
There does seem to be something of a mess in this area, in need of
cleaning up before 1.3 goes stable.
Object-based hints are not new, and haven't changed in 1.3.0 as far as I can tell. Such hints are _hints_, not type declarations (in the case of a var's value) or return type declarations (in the case of a fn held by a var). This is distinct from primitive "hints", which — in the context we've been discussing them — _are_ return type declarations (i.e. they change the type of the return from the function's generated class).
- Chas
I never said they were not hints.