请在2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解更多此工具的使用信息。

0
Java互操作

尝试获取Unicode字符串的长度,我在RosettaCode上找到了这代码,名为grapheme-length [1]

(def grapheme-length
  #(->> (doto (BreakIterator/getCharacterInstance)
          (.setText %))
        (partial (memfn next))
        repeatedly
        (take-while (partial not= BreakIterator/DONE))
        count))

我通过REPL调用它进行测试,如下所示

(star-traders.util/grapheme-length "\uD83D\uDE04⌘\uD83D\uDE00") ; Expecting 3

虽然它确实返回了预期的值,但我还收到了一条红字警告,询问我是否考虑向clojure.lang.InjectedInvoker的维护者报告这个问题...

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x0000000800cc8440 (file:/Users/myusername/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar) to method sun.text.RuleBasedBreakIterator.setText(java.text.CharacterIterator)
WARNING: Please consider reporting this to the maintainers of clojure.lang.InjectedInvoker/0x0000000800cc8440
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

这实际上是JVM的一个已知的bug,由于Java 9模块系统的添加而出现,这在Clojure FAQ中也有提及.[2]

尽管将--illegal-access=deny添加到JVM参数后问题确实消失了,但建议的解决方案还是用类型提示修复代码。

我已经尝试使用--illegal-access=warn来定位并修复问题,如下所示

          (.setText ^java.text.BreakIterator %)) ; Problem happens here (I think)

但问题仍然存在,这让我好奇我应该使用正确的类型。

我应该如何修复代码以消除编译器警告,而不是仅仅抑制警告?

[1] https://rosettacode.org/wiki/String_length#Grapheme_Length_2
[2] https://clojure.org/guides/faq#illegal_access

1 答案

+1

已选择
 
最佳答案

实际上,反射警告来自于这段代码的几行:`setText`调用和`next`调用。我相信你需要以下内容来解决这两个问题

user=> (def grapheme-length
  #(->> (doto (BreakIterator/getCharacterInstance)
          (.setText ^String %)) ; hint the argument here
        (partial (fn [^BreakIterator o] (.next o))) ; hint the object here
        repeatedly
        (take-while (partial not= BreakIterator/DONE))
        count))
#'user/grapheme-length
user=> (grapheme-length "\uD83D\uDE04⌘\uD83D\uDE00")
3
user=> 
总的来说,memfn总是因为其实现特性而引入反射
这个方法有效,Sean。谢谢。我很想知道你是如何想到这个的,但这是一个另一个日子的话题。我怀疑我没有完全理解错误信息。谢谢Alex,这也是我第一次遇到memfn。
我把我的REPL会话复制到了一个Gist并进行了注释: https://gist.github.com/seancorfield/01e42dbf3de68bab6ef3d7d6245af192
...