Static member access

31 views
Skip to first unread message

Rich Hickey

unread,
Jun 17, 2008, 7:59:29 PM6/17/08
to Clojure
I've added (in SVN) experimental static member access using classname/
member in the same style as namespace/name.

Works for fields, with no parens: Math/PI, or static method
invocations (Math/sqrt 42)

Feedback welcome,

Rich

Graham Fawcett

unread,
Jun 17, 2008, 9:16:07 PM6/17/08
to Clojure
+1 -- I like this, and the other syntactic shortcuts for Java interop.

Graham


> Rich

Albert Cardona

unread,
Jun 17, 2008, 10:11:15 PM6/17/08
to clo...@googlegroups.com


Does that mean one can import all static fields and methods of a class
into the current namespace?

Albert

--
Albert Cardona
http://www.mcdb.ucla.edu/Research/Hartenstein/acardona

Albert Cardona

unread,
Jun 17, 2008, 10:13:22 PM6/17/08
to clo...@googlegroups.com

Stephen C. Gilardi

unread,
Jun 17, 2008, 11:41:05 PM6/17/08
to clo...@googlegroups.com
On Jun 17, 2008, at 7:59 PM, Rich Hickey wrote:

> Works for fields, with no parens: Math/PI, or static method
> invocations (Math/sqrt 42)
>
> Feedback welcome,

I like it.

After a few simple examples, I tried this:

(map Math/sqrt (range 100))

which failed.

There is an easy way to get the same effect:

(map #(Math/sqrt %) (range 100))

Would it be possible (efficiently) to make a static method reference
act as a Clojure function in more contexts like as an argument to
map? I curious to know what the issues are with doing that in a
pervasive way.

I've also wondered why you chose / over : as a separator between
namespace and name. The colon seems to fit the role well (an
introducer), doesn't have an existing meaning as the division symbol,
and since keywords are not symbols, it seems using it would be
compatible with their special naming as well. I like /, but I'm
curious if you considered and rejected : and why.

Thanks,

--Steve

Guillaume Faure

unread,
Jun 18, 2008, 8:07:24 AM6/18/08
to clo...@googlegroups.com
This new syntax for static java interop seems a really good thing to me.

Thanks Rich for all your hard work on clojure.

Guillaume.

Rich Hickey

unread,
Jun 18, 2008, 8:14:00 AM6/18/08
to Clojure


On Jun 17, 10:11 pm, Albert Cardona <sapri...@gmail.com> wrote:
> Rich Hickey wrote:
> > I've added (in SVN) experimental static member access using classname/
> > member in the same style as namespace/name.
>
> > Works for fields, with no parens: Math/PI, or static method
> > invocations (Math/sqrt 42)
>
> > Feedback welcome,
>
> Does that mean one can import all static fields and methods of a class
> into the current namespace?
>

Not yet

Rich

Rich Hickey

unread,
Jun 18, 2008, 8:43:37 AM6/18/08
to Clojure


On Jun 17, 11:41 pm, "Stephen C. Gilardi" <scgila...@gmail.com> wrote:
> On Jun 17, 2008, at 7:59 PM, Rich Hickey wrote:
>
> > Works for fields, with no parens: Math/PI, or static method
> > invocations (Math/sqrt 42)
>
> > Feedback welcome,
>
> I like it.
>
> After a few simple examples, I tried this:
>
> (map Math/sqrt (range 100))
>
> which failed.
>
> There is an easy way to get the same effect:
>
> (map #(Math/sqrt %) (range 100))
>
> Would it be possible (efficiently) to make a static method reference
> act as a Clojure function in more contexts like as an argument to
> map? I curious to know what the issues are with doing that in a
> pervasive way.
>

I understand the desire for this and have been working on it. Some of
the issues are, when doing (map classname/method ...) there is very
little context for overload resolution, i.e. you have no arguments
to work with, either for arity or types. If the function is not
overloaded, it's no problem making an efficient wrapper, if it is
overloaded, then you'll need more info or have to generate reflective
calls, and supplying more info is unlikely to be more succinct than
#(), which already supports type hints on the %s. A second minor issue
is caching frequently referenced static methods wrappers rather than
whip up a wrapper at each use. A third major issue is I don't want to
see a lot of this:

(def sqrt Math/sqrt)

because the resulting wrapper functions will definitely be less inline-
able than the direct calls. So I'm also working on some kind of refer
variant that will let you pull class statics into a namespace.

> I've also wondered why you chose / over : as a separator between
> namespace and name. The colon seems to fit the role well (an
> introducer), doesn't have an existing meaning as the division symbol,
> and since keywords are not symbols, it seems using it would be
> compatible with their special naming as well. I like /, but I'm
> curious if you considered and rejected : and why.
>

I have pages and pages of syntax variants from over the years. I saw /
used in Erlang and liked it, and at the time thought : might be used
for multi-component separation. / has the advantage of not being a
shifted character - in the end that won out, as I saw people using
namespace qualifiers regularly, as in Erlang.

The non-commutative operators have always been awkward as prefix, so I
wasn't going to let division dominate.

The other reason for not using : is that : is used as a namespace
separator in XML, and that use can conflict with a language having an
interpretation of : as syntax. Dealing with that in Common Lisp is a
pain. I have recently enabled : for use by users within symbols, and
it seems like that will be useful in XML work, so I think this all
ended up ok.

Rich

Stuart Sierra

unread,
Jun 18, 2008, 10:23:58 AM6/18/08
to Clojure
On Jun 18, 8:43 am, Rich Hickey <richhic...@gmail.com> wrote:
> A third major issue is I don't want to see a lot of this:
>
> (def sqrt Math/sqrt)
>
> because the resulting wrapper functions will definitely be less inline-
> able than the direct calls. So I'm also working on some kind of refer
> variant that will let you pull class statics into a namespace.

For what it's worth, I wrote a cheese-ball lib that lets you do this:

(import-static java.lang.Math sqrt PI)
(sqrt PI)

I cheated and def'd macros for the static functions. It's clojure-
contrib/import-static.clj

-S

Chouser

unread,
Jun 18, 2008, 10:59:09 AM6/18/08
to clo...@googlegroups.com
user=> (in-ns 'Math)
#<Namespace: Math>

You see where I'm going, don't you.

Math=> (def PI 3.14)
#'Math/PI
Math=> (clojure/in-ns 'user)
#<Namespace: user>

And now the fun:

user=> Math
class java.lang.Math
user=> Math/PI
3.14

Now everyone can pretend to live in Indiana!
Perhaps I'm only getting what I deserve, but should there be a warning
or something?

--Chouser

Rich Hickey

unread,
Jun 18, 2008, 11:35:20 AM6/18/08
to Clojure


On Jun 18, 10:59 am, Chouser <chou...@gmail.com> wrote:
> user=> (in-ns 'Math)
> #<Namespace: Math>
>
> You see where I'm going, don't you.
>
> Math=> (def PI 3.14)
> #'Math/PI
> Math=> (clojure/in-ns 'user)
> #<Namespace: user>
>
> And now the fun:
>
> user=> Math
> class java.lang.Math
> user=> Math/PI
> 3.14
>
> Now everyone can pretend to live in Indiana!
> Perhaps I'm only getting what I deserve,

Yes :)

> but should there be a warning
> or something?
>

A warning when?

As a general rule, Java classes begin with upper case and Clojure
names eschew upper case, so I consider this a non-problem,
practically. The behavior will generally be defined as you've found it
to be - namespaces win. I suppose there might even be non-evil
applications of that fact. In the specific case you have, I could (and
probably will) make the (imported) class win. But I can't do the same
with non-imported fully-qualified names.

I can certainly disallow namespaces with the same names as java.lang.*
classes, but not generally disallow namespaces with the same names as
classes, as both are open sets.

One way to look at this is as a unification of Java package and
Clojure namespace namespaces, where the same com.mydomain.name
convention will be used to prevent conflict.

This is work in progress, but some ideas are an import-like thing for
Clojure namespaces so you can drop the com.mydomain part, and/or alias
it, and some flavor of refer for Java classes that will bring static
members in without classname qualifiers.

Rich

Chouser

unread,
Jun 18, 2008, 11:47:53 AM6/18/08
to clo...@googlegroups.com
On Wed, Jun 18, 2008 at 11:35 AM, Rich Hickey <richh...@gmail.com> wrote:
> A warning when?
>
> As a general rule, Java classes begin with upper case and Clojure
> names eschew upper case, so I consider this a non-problem,
> practically.
[clip]

> I can certainly disallow namespaces with the same names as java.lang.*
> classes, but not generally disallow namespaces with the same names as
> classes, as both are open sets.

That's why I mentioned a warning as opposed to disallowing. If you've
already imported java.lang.Math, (in-ns 'Math) could generate a
warning. If you've already got a Date namespace, then (import
'(java.util Date)) could generate a warning.

Although I suppose then people would want a way to suppress the
warning when they think they know what they're doing.

Perhaps you're right that capitalization will be enough to keep things straight.

--Chouser

Reply all
Reply to author
Forward
0 new messages