Java method call irritation

90 views
Skip to first unread message

alux

unread,
Mar 18, 2010, 6:15:02 AM3/18/10
to Clojure
Hello, I just was to lazy to get my Javadoc, so I wanted to list the
methods of an object from the 1.1-REPL.

I got different results when mapping .getName or #(.getName %) over
the seq I produced - I expected this to be the same. So seemingly my
expectations are wrong. Would you please rectify?

(map .getName (-> (Runtime/getRuntime) .getClass .getMethods seq))

got

java.lang.Exception: Unable to resolve symbol: .getName in this
context

but the following worked fine:

(map #(.getName %) (-> (Runtime/getRuntime) .getClass .getMethods
seq))


Thanks for any help, alux

Meikel Brandmeyer

unread,
Mar 18, 2010, 6:21:27 AM3/18/10
to Clojure
Hi,

Java methods are not clojure functions. To treat them like first-class
functions you have to wrap them in clojure functions as you did in
your second example.

For your actual task: you might want to look at clojure.contrib.repl-
utils/show.

Sincerely
Meikel

alux

unread,
Mar 18, 2010, 6:32:43 AM3/18/10
to Clojure
Thank you Meikel. I just didnt encounter that information before ;-)

I'm still in the process of learning the core lib, so while learning I
sometimes avoid the contrib libraries, and try myself. Here this
proved educating again ;-)
(wouldn't do so for production ;-)

Thank you and regards, alux

Seth

unread,
Mar 18, 2010, 8:26:46 AM3/18/10
to Clojure
This seems like a potential usecase for (memfn):

-------------------------
clojure.core/memfn
([name & args])
Macro
Expands into code that creates a fn that expects to be passed an
object and any args and calls the named instance method on the
object passing the args. Use when you want to treat a Java method as
a first-class fn.

user> (= (map (memfn getName) (-> (Runtime/
getRuntime) .getClass .getMethods seq))
(map #(.getName %) (-> (Runtime/
getRuntime) .getClass .getMethods seq)))
true

Stuart Halloway

unread,
Mar 18, 2010, 10:50:10 AM3/18/10
to clo...@googlegroups.com
memfn is from the depths of time and should be deprecated -- it is
idiomatic to write an anonymous fn around the method.

Stu

> --
> 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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

Per Vognsen

unread,
Mar 18, 2010, 11:55:24 AM3/18/10
to clo...@googlegroups.com
Is there any reason why a .method occurrence in non-operator position
doesn't just do the closure wrapping automagically?

-Per

Seth

unread,
Mar 18, 2010, 2:36:48 PM3/18/10
to Clojure
Would :deprecated be a reasonable thing to include in a function's
metadata? Just the presence of it seems good enough, but I guess
pairing it with some programmer friendly message ("hey, use bar
instead of foo") might be nice.

Or... maybe 10,000 lines of XML as metadata! :-)

On Mar 18, 10:50 am, Stuart Halloway <stuart.hallo...@gmail.com>
wrote:

> >http://groups.google.com/group/clojure?hl=en- Hide quoted text -
>
> - Show quoted text -

Sean Devlin

unread,
Mar 18, 2010, 3:02:06 PM3/18/10
to Clojure
And upgrade the doc macro accordingly? That would make entirely too
much sense.

+1

> > >http://groups.google.com/group/clojure?hl=en-Hide quoted text -

Michael Gardner

unread,
Mar 18, 2010, 5:30:37 PM3/18/10
to clo...@googlegroups.com
On Mar 18, 2010, at 10:55 AM, Per Vognsen wrote:

> Is there any reason why a .method occurrence in non-operator position
> doesn't just do the closure wrapping automagically?

I'd like to know this as well. Smooth Java interop is one of Clojure's selling points, but having to wrap Java methods in lambdas to use them as first-class functions feels awkward. Especially if the method in question has multiple arguments!

-Michael

Per Vognsen

unread,
Mar 19, 2010, 12:48:47 AM3/19/10
to clo...@googlegroups.com
My experience as a newcomer to Clojure is that one of the most
surprising things is the dichotomy between the Clojure and JVM world.

I was reading one of Lau's blog posts on converting images to ASCII art:

http://www.bestinclass.dk/index.php/2010/02/my-tribute-to-steve-ballmer

His get-properties macro is only really needed because of this issue
with methods. If .methods were wrapped up as clojures, you could write
it directly like this:

;; General purpose function. Useful whenever you want to reverse the
sense of function and arguments.
(defn with-args [& args]
#(apply % args))

(map (with-args (.getRGB image 10 10)) [.getRed .getGreen .getBlue])

-Per

> --
> 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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>

> To unsubscribe from this group, send email to clojure+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.
>

Laurent PETIT

unread,
Mar 19, 2010, 2:14:58 AM3/19/10
to clo...@googlegroups.com
Hi,

In this particular case, his get-properties macros was a demonstration
of how to write a macro, but could have been replaced with an
out-of-the-box clojure.core/bean call.

2010/3/19 Per Vognsen <per.v...@gmail.com>:

Konrad Hinsen

unread,
Mar 19, 2010, 3:46:17 AM3/19/10
to clo...@googlegroups.com
On 18 Mar 2010, at 16:55, Per Vognsen wrote:

> Is there any reason why a .method occurrence in non-operator position
> doesn't just do the closure wrapping automagically?

There is two reasons I can think of, though of course I can't know if
they are the real ones.

First, a technical reason: .method is handled as part of macro
expansion:

user> (macroexpand-1 '(.hashCode 3))
(. 3 hashCode)

The result is a special form for Java interop. Symbols in non-operator
positions are not macro-expanded, so some other mechanism would have
to be invented to handle them in a special way. It would in fact
create a first "special symbol" category, complicating the semantics
of the language, so this is not just a technical reason.

Second, a semantic reason: Java method calls are resolved statically
if possible (you can use reflection warnings to find out where this
fails), making them very fast. Creating and calling a closure is a
much slower operation. Rich has stated at several occasions that he
considers performance in important part of the interface of a
function, so making a clear syntactic distinction between a fast and a
slow operation would fit well with that point of view.

Konrad.

Per Vognsen

unread,
Mar 19, 2010, 4:04:35 AM3/19/10
to clo...@googlegroups.com
On Fri, Mar 19, 2010 at 2:46 PM, Konrad Hinsen
<konrad...@fastmail.net> wrote:
> On 18 Mar 2010, at 16:55, Per Vognsen wrote:
>
>> Is there any reason why a .method occurrence in non-operator position
>> doesn't just do the closure wrapping automagically?
>
> There is two reasons I can think of, though of course I can't know if they
> are the real ones.
>
> First, a technical reason: .method is handled as part of macro expansion:
>
>        user> (macroexpand-1 '(.hashCode 3))
>        (. 3 hashCode)
>
> The result is a special form for Java interop. Symbols in non-operator
> positions are not macro-expanded, so some other mechanism would have to be
> invented to handle them in a special way. It would in fact create a first
> "special symbol" category, complicating the semantics of the language, so
> this is not just a technical reason.

Interesting. I had tacitly assumed there was already some "special
symbol" magic going on and so did not know it was a simple case of
macro expansion with a little reader support.

>
> Second, a semantic reason: Java method calls are resolved statically if
> possible (you can use reflection warnings to find out where this fails),
> making them very fast. Creating and calling a closure is a much slower
> operation. Rich has stated at several occasions that he considers
> performance in important part of the interface of a function, so making a
> clear syntactic distinction between a fast and a slow operation would fit
> well with that point of view.

I thought of this as well before posting. A few comments:

1. Creation: You only need to create one closure per function, once
and for all; the closure does not close over anything in the
surrounding scope, it's just a wrapper.
2. Calling: This is such a straightforward case of inlining that
HotSpot will eat it for breakfast. Clojure is full of idioms that
would be death to performance if not for such behavior from HotSpot.
3. Type hinting: This is a deeper problem with first-class methods.
The current manner of type hinting does not work well here. If you
could write SomeClass.someMethod to refer to a specific class's method
and perhaps supply further signature hints in the case of same-arity
overloads, e.g. #^([Integer]) ResultSet.getObject, then this could be
resolved.

-Per

> Konrad.


>
> --
> 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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>
> To unsubscribe from this group, send email to

LauJensen

unread,
Mar 19, 2010, 4:10:15 AM3/19/10
to Clojure
Konrad,

Im not following where this would be a problem in terms of
optimization. In the definition for map,
all that needs to be added is a check for a symbol? and the resulting
sequence could look and act
exactly like it would, had you manually added the #(.method %) right?

If the technical obstacle can be overcome, which Im confident that it
can, then regarding semantics
this have come up several times, where people intuitively assume that
it works, which I completely
understand and think it should, so it wouldn't be adding a layer of
complexity.

Lau

Per Vognsen

unread,
Mar 19, 2010, 4:13:52 AM3/19/10
to clo...@googlegroups.com
I don't think passing symbols around and having special case behavior
scattered around different functions is going to help beginners. If
anything, it would confuse them when they try to treat .methods as
first-class functions in their own code and discover that it doesn't
work.

-Per

> --
> 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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>

> To unsubscribe from this group, send email to clojure+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.
>

Laurent PETIT

unread,
Mar 19, 2010, 8:56:55 AM3/19/10
to clo...@googlegroups.com
Where would you place the type hint needed to avoid reflection ?

2010/3/19 LauJensen <lau.j...@bestinclass.dk>:

> --
> 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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>

Chouser

unread,
Mar 19, 2010, 9:27:22 AM3/19/10
to clo...@googlegroups.com

This has been discussed some, including alternate hinting
syntaxes not entirely unlike what you suggest:

http://clojure-log.n01se.net/date/2010-01-21.html#08:34

--Chouser
http://joyofclojure.com/

Stuart Sierra

unread,
Mar 19, 2010, 4:14:50 PM3/19/10
to Clojure
On Mar 18, 11:55 am, Per Vognsen <per.vogn...@gmail.com> wrote:
> Is there any reason why a .method occurrence in non-operator position
> doesn't just do the closure wrapping automagically?

It's been discussed as a possibility; it may be added to Clojure in
the future.

-SS

Reply all
Reply to author
Forward
0 new messages