type-hints positioning convention?

142 views
Skip to first unread message

Jim - FooBar();

unread,
Jun 17, 2013, 7:59:47 AM6/17/13
to clo...@googlegroups.com
Hi all,

It seems to me that return type-hints can go either right after "defn",
or after the doc-string. I generally, put the return type-hints right
before the argument vector and it seems to get rid of reflection.
However, I just had a look at core.contrib.strutils2 and the author(s)
put the type hint right after 'defn' (before the var about to be
defined) and again it gets rid of reflection! Which one is it? both are
acceptable?

thanks in advance,

Jim

Stuart Sierra

unread,
Jun 17, 2013, 12:03:22 PM6/17/13
to clo...@googlegroups.com
I don't know what "core.contrib.strutils2" is, but it sounds like "old contrib" pre-clojure-1.3.
See http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

The type-hints-before-the-argument-vector syntax was introduced in Clojure 1.3 along with primitive type hints, so I would consider it the more current style.

The older type-hint-before-the-symbol syntax is still supported, and probably won't go away any time soon.

-S

Jim - FooBar();

unread,
Jun 17, 2013, 12:07:31 PM6/17/13
to clo...@googlegroups.com
On 17/06/13 17:03, Stuart Sierra wrote:
> The type-hints-before-the-argument-vector syntax was introduced in
> Clojure 1.3 along with primitive type hints, so I would consider it
> the more current style.
>
> The older type-hint-before-the-symbol syntax is still supported, and
> probably won't go away any time soon.
>
> -S


I see...

thanks Stuart :)

Jim

Ambrose Bonnaire-Sergeant

unread,
Jun 17, 2013, 12:59:53 PM6/17/13
to clojure
After some investigation, the before-the-arglist syntax only seems useful for defining fn's that return primitive types.
They don't seem to help resolve reflection calls.

(require '[clojure.tools.analyzer :refer [ast]])

; this creates a double-emitting fn

(ast (fn (^double [^double a] a)))
; =>
;{:op :fn-expr,
; ...
; :methods
; ({:op :fn-method,
;   ...
;   :arg-types (#<Type Ljava/lang/Object;>),
;   :return-type #<Type D>}),   ;double return type here
;  ...
; :tag nil}  ; no tag

; this creates a regular old fn

(ast (fn (^String [a] 1))) 
; =>
;{:op :fn-expr,
; ... 
; ({:op :fn-method,
;   ...
;   :arg-types (#<Type Ljava/lang/Object;>),
;   :return-type #<Type Ljava/lang/Object;>}),  ;object return type
; ...
; :tag nil}  ; no tag

; this creates a String-hinted fn

(ast ^String (fn a [a] 1))
;{:op :meta,
; ...
; :expr
; {:op :fn-expr,
;  ...
;  :methods
;  ({:op :fn-method,
;    :arg-types (#<Type Ljava/lang/Object;>),
;    :return-type #<Type Ljava/lang/Object;>}),
;  ...
;  :tag String}}

I don't see where before-the-arglist is useful outside of primitive fns.

Thanks,
Ambrose



--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



Jim - FooBar();

unread,
Jun 17, 2013, 1:10:03 PM6/17/13
to clo...@googlegroups.com
so how about this then?


nREPL server started on port 43830
REPL-y 0.2.0
Clojure 1.5.1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)

user=> (set! *warn-on-reflection* true)
true
user=> (defn foo [^String s] (.substring s 0 (.length s)))
#'user/foo
user=> (foo "jim")
"jim"
user=> (.length (foo "jim"))
Reflection warning, NO_SOURCE_PATH:1:1 - reference to field length can't be resolved.
3
user=> (defn foo ^String [^String s] (.substring s 0 (.length s)))
#'user/foo
user=> (.length (foo "jim"))
3
user=> (defn ^String  foo [^String s] (.substring s 0 (.length s)))
#'user/foo
user=> (.length (foo "jim"))
3


it worked both times didn't it?

Jim
Ambrose


For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.


--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.

Ambrose Bonnaire-Sergeant

unread,
Jun 17, 2013, 1:15:28 PM6/17/13
to clojure
Yes, it did. That's interesting. I have no idea where the .length method is being inferred from in the last example.

Carry on :)

Ambrose

Ambrose Bonnaire-Sergeant

unread,
Jun 17, 2013, 1:33:00 PM6/17/13
to clojure
Seems like there's some trickery involved with using Vars.

This example seems to use reflection.

user=> (.length ((fn ^String [^String s] (.substring s 0 (.length s))) "a"))
Reflection warning, NO_SOURCE_PATH:1:1 - reference to field length can't be resolved.
1

Thanks,
Ambrose

Jim - FooBar();

unread,
Jun 17, 2013, 1:38:20 PM6/17/13
to clo...@googlegroups.com
OK now I'm confused! If you are using an unnamed  fn form there is only one place to put the return type-hin,t and that is between the 'fn' and the '[...]'
...but, you've just demonstrated that this causes reflection...where else can we put it?

Jim

Ambrose Bonnaire-Sergeant

unread,
Jun 17, 2013, 2:04:45 PM6/17/13
to clojure
I'm not sure. I guess we're stuck with tagging locals at that point?

Thanks,
Ambrose

Alan Malloy

unread,
Jun 17, 2013, 2:46:25 PM6/17/13
to clo...@googlegroups.com, abonnair...@gmail.com
Typehints for functions are only useful on vars. There is no code anywhere, as far as I know, that looks at the metadata attached to anonymous functions.
Reply all
Reply to author
Forward
0 new messages