English 中文(简体)
taking java method names as function arg in clojure
原标题:

All,

I want to create a function that takes a symbol representing a java method and applies it to some object:

(user=> (defn f [m] (. "foo" (m)))

When I execute this, I get a result much different from what I expect

user=> (f  getClass)
java.lang.IllegalArgumentException: No matching method found: m for class java.lang.String (NO_SOURCE_FILE:0)

2 questions:

1> why is the symbol m being called as the second arg of the . function instead of the value bound to m?

2> how would I actually do what I want to do?

最佳回答

It s not working because . is a special form and has special evaluation rules. Normal function calls evaluate their arguments, but . doesn t evaluate the method-name parameter.

To make it work, either use eval or change your function into a macro.

user=> (defmacro foo [o m] `(. ~o ~m))
# user/foo
user=> (foo 123 toString)
"123"
user=> (defn bar [o m] (eval `(. ~o ~m)))
# user/bar
user=> (bar 123  toString)
"123"

Use of eval generally isn t recommended.

问题回答

The problem is that the method calls are hard-wired in the JVM bytecode. As Brian states, eval will work, because it compiles the code each time it is called. However stay away from eval. It has its uses, but this one is not one of them.

The best way is to do what you want is to use reflection. Or if possible use the macro Brian showed. Reflection can be done via:

(defn f
  [m & args]
  (clojure.lang.Reflector/invokeInstanceMethod obj m (into-array Object args)))

Not really tested, though...

The macro Brian alludes to exists already, and is called memfn, for "member function".

user> ((memfn length) "test")
4




相关问题
Why I can t pass two chars as function arguments in C?

I have a function: int get_symbol(tab *tp, FILE *fp, char delim) and I call it like this: get_symbol(tp, fp, ; ) I always have it declared in the header as: int get_symbol(tab *, FILE *, char); ...

problem w/ linking static function g++

I am trying to build a small program and I have my own library libfoo. I have a camera class that is calling a static function from my Vector3 class (i.e. crossProduct). My camera class and Vector3 ...

taking java method names as function arg in clojure

All, I want to create a function that takes a symbol representing a java method and applies it to some object: (user=> (defn f [m] (. "foo" (m))) When I execute this, I get a result much ...

Def, Void, Function?

Recently, I ve been learning different programming langages, and come across many different names to initalize a function construct. For instance, ruby and python use the def keyword, and php and ...

热门标签