why the def of run-jetty looks like "defn #^Server run-jetty"

24 views
Skip to first unread message

limux

unread,
Aug 9, 2010, 2:25:27 AM8/9/10
to Clojure
The follow is the ring's source, and I am a newbie in Clojure.
what the defn of run-jetty looks like this form, what's the meaning of
#^Server in the defn and let?

Thanks in advance.
Limux.
(defn #^Server run-jetty
"Serve the given handler according to the options.
Options:
:configurator - A function called with the Server instance.
:port
:host
:join? - Block the caller: defaults to true.
:ssl? - Use SSL.
:ssl-port - SSL port: defaults to 443, implies :ssl?
:keystore
:key-password
:truststore
:trust-password"
[handler options]
(let [#^Server s (create-server (dissoc options :configurator))]
(when-let [configurator (:configurator options)]
(configurator s))
(doto s
(.setHandler (proxy-handler handler))
(.start))
(when (:join? options true)
(.join s))
s))

j-g-faustus

unread,
Aug 9, 2010, 3:04:42 AM8/9/10
to Clojure
On Aug 9, 8:25 am, limux <liumengji...@gmail.com> wrote:
> what's the meaning of
> #^Server in the defn and let?
> (defn #^Server run-jetty
...
>   (let [#^Server s (create-server (dissoc options :configurator))]

It's a type hint. In the defn it specifies the type of the return
value, in the let it gives the type of the var.
#^... is the Clojure 1.1 syntax, in 1.2 it has changed to ^...

Type hints are optional. See http://clojure.org/java_interop#Java%20Interop-Type%20Hints


Regards

jf

limux

unread,
Aug 9, 2010, 3:31:41 AM8/9/10
to Clojure
I see, heartly thanks, and there is no any words about it in API doc
of clojure.org yet!

Regards
limux.

limux

unread,
Aug 9, 2010, 3:40:37 AM8/9/10
to Clojure
The type hint can be placed on function parameters, let-bound names,
var names, and expressions.

And it can be placed behind or ahead of them. Isn't it?

Nicolas Oury

unread,
Aug 9, 2010, 4:47:25 AM8/9/10
to clo...@googlegroups.com
I am not 100% sure, but it seems they are always ahead.

(defn ^Bar foo ...)

tells that function foo returns something of class Bar.

(f ^Bar expr) says that expr is of type Bar.

(let [ ^Bar e expr] ... says that e is of type Bar.

(Bar can be a class or an interface.)

The main usage (at least for me) is avoiding reflection in the context
of direct call to a Java method.

if you write:
(defn foo [x]
(.clone x))

For Clojure, x is an object and so it does not know anything about its
interface (the methods it understands). So it cannot do better than a
"dynamic dispatch", looking at x class by reflection and searching for
a method named clone with the right signature.
It can be long, and so should be avoided on code that is called more
than rarely.
To avoid that:

(defn foo [^Clonable x]
(.clone x))
Now, Clojure knows at compile-time that x is Clonable.
It can check that clone is in the known interface and use a direct
method call, which is faster.

(set! *warn-on-reflection* true)
makes the compiler emit a warning in the first case.

You should remark that this kind of problem only occurs when
interfacing directly with the host language.

Other usages may happen, like when a specific signatures is needed for
interoperability.


Hope I am not too wrong and that helps.

Nicolas

ngocdaothanh

unread,
Aug 10, 2010, 4:14:30 AM8/10/10
to Clojure
> The main usage (at least for me) is avoiding reflection in the context
> of direct call to a Java method.
>
> if you write:
> (defn foo [x]
>   (.clone x))

Thank you for the insightful explanation.
Reply all
Reply to author
Forward
0 new messages