如何将 Java 类中的“static final”常量拉入 Clojure 命名空间?
我正在尝试使用 Clojure 绑定包装 Java 库。 Java 库中的一个特定类定义了一堆静态最终常量,例如:
class Foo {
public static final int BAR = 0;
public static final int SOME_CONSTANT = 1;
...
}
我有一个想法,我可能能够检查该类并将这些常量拉入我的 Clojure 命名空间,而无需显式 def
-每一个。
例如,不需要像这样显式连接它:
(def foo-bar Foo/BAR)
(def foo-some-constant Foo/SOME_CONSTANT)
我可以检查 Foo 类并动态连接 foo-bar 和 foo-some加载模块时,我的 Clojure 命名空间中的 -constant 。
我认为这样做有两个原因:
A) 在将新常量添加到 Foo
类中时自动引入新常量。换句话说,如果 Java 接口添加了新常量,我就不必修改 Clojure 包装器。
B) 我可以保证这些常量遵循更类似于 Clojure 风格的命名约定,
我并不真正愿意这样做,但这似乎是一个很好的问题,可以扩展我对 Clojure/Java 互操作的知识。
谢谢
I am trying to wrap a Java library with a Clojure binding. One particular class in the Java library defines a bunch of static final constants, for example:
class Foo {
public static final int BAR = 0;
public static final int SOME_CONSTANT = 1;
...
}
I had a thought that I might be able to inspect the class and pull these constants into my Clojure namespace without explicitly def
-ing each one.
For example, instead of explicitly wiring it up like this:
(def foo-bar Foo/BAR)
(def foo-some-constant Foo/SOME_CONSTANT)
I'd be able to inspect the Foo
class and dynamically wire up foo-bar
and foo-some-constant
in my Clojure namespace when the module is loaded.
I see two reasons for doing this:
A) Automatically pull in new constants as they are added to the Foo
class. In other words, I wouldn't have to modify my Clojure wrapper in the case that the Java interface added a new constant.
B) I can guarantee the constants follow a more Clojure-esque naming convention
I'm not really sold on doing this, but it seems like a good question to ask to expand my knowledge of Clojure/Java interop.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
遗憾的是,宏clojure.contrib.import-static不允许导入所有静态最终字段。您必须提供要导入的字段列表。
这个宏是 import-static 的惯用包装:
Sadly the macro clojure.contrib.import-static doesn't allow to import all static final fields. You must provide a list of fields to import.
This macro is a idiomatic wrapper for import-static:
(这个答案现在包括两个可行的解决方案,一个基于我对
intern
的最初想法,另一个基于 danlei 使用ccimport-static
的建议。我想我'稍后需要清理它,但我现在不能花更多时间在上面...)要提取静态字段:
Then map#(intern *ns* (str "a-prefix-" (.getName %)) (.get YourClass nil))
穿过该序列来获取值...请注意,此位未经测试,特别是,我不确定.get
中的nil
;尝试一下java.lang.Field
并看看什么适用于您的类。更新 2:
好的,实际上是基于
intern
的方法从可读性角度来看,这并不是那么糟糕:更新: (将第一个更新保留为替代解决方案)
结合 danlei 对
clojure.contrib
的了解上面的结果如下:它使用
eval
...好吧,那又怎么样,它几乎不会“杀死性能”,而且它实际上相当可读,这是一个使用intern
的复杂表达式代码> 可能不是。 (实际上并没有那么糟糕...:-))如果你更喜欢intern
,那么至少要实现import-static 如果我上面的草图被证明是不正确的,可以给你正确的想法。
(This answer now includes two working solutions, one based on my initial idea with
intern
and one based on danlei's suggestion to usec.c.import-static
. I guess I'll need to clean this up a bit later, but I can't spend more time on it now...)To extract static fields:
Then map#(intern *ns* (str "a-prefix-" (.getName %)) (.get YourClass nil))
across that sequence to obtain the value... Note that this bit is untested and, in particular, I'm not sure about thatnil
in.get
; experiment withjava.lang.Field
and see what works with your class.Update 2:
Ok, actually an
intern
based approach is not that bad readability-wise:Update: (leaving the first update in place as an alternative solution)
Combining danlei's knowledge of
clojure.contrib
with the above yields the following:It uses
eval
... well, so what, it's hardly going to "kill performance" and it's actually fairly readable, which an elaborate expression usingintern
might not be. (It's not so bad actually... :-))If you preferintern
, though, at least the implementation ofimport-static
can give you the proper ideas if my sketch above turns out to be incorrect somehow.我还没有尝试过,但也许 clojure.contrib.import-static 可以做到。
刚刚检查:使用 import-static 时,您必须命名方法/字段,但我会将这个答案留在这里,因为它可能对搜索相关答案的人有所帮助。
I haven't tried it, but maybe clojure.contrib.import-static can do it.
Just checked: You will have to name the methods/fields when using import-static, but I'll leave this answer here because it might be helpful for people searching for related answers.