2024 Clojure状态调查!中分享你的看法。

欢迎!请查看关于页面以获取更多相关信息。

+1
语法和读取器
tags修改

我在对话框上挂了一个WindowListener并得到了这个错误

$ clj windowlistener.clj
WARNING: When invoking clojure.main, use -M
Syntax error (IllegalArgumentException) compiling reify* at (windowlistener.clj:9:10).
Can't define method not in interfaces: windowIconified​

以下是代码。你能看出问题吗?

(import 'javax.swing.JOptionPane
        'java.awt.event.WindowListener)
(let [jdialog (.createDialog
               (JOptionPane. (System/getProperty "java.version"))
               "WindowListener")
      wl (reify WindowListener
           (windowActivated [this e])
           (windowClosed [this e]) 	
           (windowClosing [this e]) 	
           (windowDeactivated [this e]) 	
           (windowDeiconified [this ​e]) 	
           (windowIconified​ [this e])
           (windowOpened [this ​e]))]
  (.addWindowListener jdialog wl)
  (.show jdialog))

我知道方法名拼写正确,因为我从Firefox的Javadoc显示中粘贴了它,然后重新排列了括号。哈哈,复制粘贴是我的错误!以下是十六进制转储的结果

$ od -tcx1 ~/windowlistener.clj
...
0000700                               (   w   i   n   d   o   w   I   c
         20  20  20  20  20  20  20  28  77  69  6e  64  6f  77  49  63
0000720   o   n   i   f   i   e   d 342 200 213       [   t   h   i   s
         6f  6e  69  66  69  65  64  e2  80  8b  20  5b  74  68  69  73
0000740       e   ]   )      \t  \n                                    

那个342 200 213e2 80 8b是什么东西?我猜文件使用的是UTF-8,在这种情况下,这些字节表示代码点0x200b(通过位操作[2]),它表示UNICODE中的“ZERO WIDTH SPACE”。[3]

(顺便说一下,我在Oracle的网页上没有找到这些字节。也许Firefox为了剪贴板的好处,在元素之间插入了ZERO WIDTH SPACE。)

我很惊讶编译器将ZERO WIDTH SPACE视为符号字符。这种行为与javac不同。根据Character,ZERO WIDTH SPACE是标识符可忽略的。

$ clj
Clojure 1.10.1
user=> (Character/isIdentifierIgnorable 0x200b)
true

UNICODE巧妙地建议“为了安全起见”缩小标识符字符集合[4],据信是因为用看不见的区别来编写代码是一种没有合法用途的力量。

确实,javac忽略了ZERO WIDTH SPACE:在“public static void main”中的“main”中间插入ZERO WIDTH SPACE,程序仍然可以正常工作。[5] 如果没有这样的先例,我可能更愿意直接拒绝“可忽略”的字符,但我会用代码检查器来实现。

而且,我抱怨错误消息没有清楚地说明问题。javac通过首先剔除标识符可忽略的字符来避开这个挑战,因此没有需要揭示的不可见方面。无论如何,并非所有不慎使用的ZERO WIDTH SPACE都会立即导致编译器错误。我从javadoc粘贴的代码中充满了它们,包括附在参数名上,这不会导致错误,直到以后——而且很可能,错误将涉及“正确”的拼写,而不是受感染的拼写。

总之,出于人道主义原因,我们能否建议Clojure通过忽略它们(如javac所做)或将它们视为错误来将“标识符可忽略”的字符排除在符号之外?

[1] https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/event/WindowListener.html

[2] https://en.wikipedia.org/wiki/UTF-8#Encoding

[3] https://util.unicode.org/UnicodeJsps/character.jsp?a=200B

[4] http://unicode.org/reports/tr31/#Figure_Code_Point_Categories_for_Identifier_Parsing

[5] 可以使用 Unicode 字面量来完成

class A {
    public static void m\u200bain(String[] args) throws Exception {
        System.out.println("Hello world!");
    }
}

1 个答案

0
by
...