Scala 中的有效标识符字符

Posted

技术标签:

【中文标题】Scala 中的有效标识符字符【英文标题】:Valid identifier characters in Scala 【发布时间】:2011-12-01 04:46:27 【问题描述】:

我觉得很困惑的一件事是知道我可以在方法名和变量名中使用哪些字符和组合。比如

val #^ = 1 // legal
val #  = 1 // illegal
val +  = 1 // legal
val &+ = 1 // legal
val &2 = 1 // illegal
val £2 = 1 // legal
val ¬  = 1 // legal

据我了解,字母数字标识符运算符标识符是有区别的。您可以混合匹配一个或另一个,但不能同时混合,除非用下划线分隔(混合标识符)。

来自Scala 中的编程第 6.10 节,

操作员标识符由一个或多个操作员字符组成。 运算符字符是可打印的 ASCII 字符,例如 +、:、?、~ 要么 #。

更准确地说,运算符字符属于 Unicode 集 数学符号 (Sm) 或其他符号 (So) 或 7 位 非字母、数字、括号、正方形的 ASCII 字符 方括号、花括号、单引号或双引号或下划线, 句点、分号、逗号或反引号字符。

所以我们被排除在使用()[]'"_.;, 和`

我在 Wikipedia 上查找了 Unicode 数学符号,但我发现的那些不包括 +:? 等。是否有明确的列表来说明运算符字符是什么?

还有,为什么 Unicode 数学运算符(而不是符号)不能算作运算符?

【问题讨论】:

我特别想念²。 Scala 承诺可以编写使用巧妙的变量(和方法)名称的代码。但是你不能给变量 x² 赋值。非法字符。 【参考方案1】:

使用反引号来逃避限制并使用 Unicode 符号

val `r→f` = 150
println(`r→f`)

【讨论】:

【参考方案2】:

The language specification。给出了第 1 章词汇语法(第 3 页)中的规则:

    运算符字符。这些包括所有可打印的 ASCII 字符 \u0020-\u007F。不在上述任何一组中, 数学符号 (Sm) 和其他符号 (So)。

这与您摘录的 Programming in Programming in Scala 基本相同。 + 不是 Unicode 数学符号,但绝对是上面未列出的 ASCII printable character(不是字母,包括 _ 或 $、数字、括号、分隔符)。

在您的列表中:

    # 非法不是因为字符不是操作符字符 (#^ 是合法的),但因为它是保留字(第 4 页),用于类型投影。 &2 是非法的,因为你混合了一个运算符字符 & 和一个非运算符字符,数字 2 £2 是合法的,因为 £ 不是运算符字符:它不是 7 位 ASCII,而是 8 位扩展 ASCII。这不好,因为$ 也不是一个(它被认为是一封信)。

【讨论】:

“数学符号(Sm)和其他符号(So)”是“包含”还是“不包含”的对象?【参考方案3】:

使用规范中的 EBNF 语法:

upper ::= ‘A’ | ... | ‘Z’ | ‘$’ | ‘_’ and Unicode category Lu
lower ::= ‘a’ | ... | ‘z’ and Unicode category Ll
letter ::= upper | lower and Unicode categories Lo, Lt, Nl
digit ::= ‘0’ | ... | ‘9’
opchar ::= “all other characters in \u0020-007F and Unicode
            categories Sm, So except parentheses ([]) and periods”

但也考虑到词法语法的最开始定义:

Parentheses ‘(’ | ‘)’ | ‘[’ | ‘]’ | ‘’ | ‘’.
Delimiter characters ‘‘’ | ‘’’ | ‘"’ | ‘.’ | ‘;’ | ‘,’

这是我想出的。通过消除\u0020-007F 范围内的工作,消除字母、数字、括号和分隔符,我们有 opchar...(鼓声):

! # % & * + - / : < = > ? @ \ ^ | ~ 还有SmSo - 括号和句点除外。

(编辑:在此处添加有效示例:)。总之,这里有一些突出所有案例的有效示例 - 注意 REPL 中的 \,我不得不以 \\ 转义:

val !#%&*+-/:<=>?@\^|~ = 1 // all simple opchars
val simpleName = 1 
val withDigitsAndUnderscores_ab_12_ab12 = 1 
val wordEndingInOpChars_!#%&*+-/:<=>?@\^|~ = 1
val !^©® = 1 // opchars ans symbols
val abcαβγ_!^©® = 1 // mixing unicode letters and symbols

注1:

我找到了这个 Unicode category index 来找出Lu, Ll, Lo, Lt, Nl

Lu(大写字母) Ll(小写字母) Lo​​(其他字母) Lt(标题) Nl(字母数字,如罗马数字) Sm(符号数学) 所以(其他符号)

注2:

val #^ = 1 // legal   - two opchars
val #  = 1 // illegal - reserved word like class or => or @
val +  = 1 // legal   - opchar
val &+ = 1 // legal   - two opchars
val &2 = 1 // illegal - opchar and letter do not mix arbitrarily
val £2 = 1 // working - £ is part of Sc (Symbol currency) - undefined by spec
val ¬  = 1 // legal   - part of Sm

注3:

其他类似于运算符的保留字:_ : = =&gt; &lt;- &lt;: &lt;% &gt;: # @ 以及 \u21D2 ⇒ 和 \u2190

【讨论】:

谢谢。此外,正如规范所说,我们仅限于 Unicode 基本多语言平面字符,即 \ufffd 上的 2 字节字符。因此,从So 开始,\u262f 阴阳运算符是合法的,但 \u1f360 不支持烤红薯运算符(它被解释为 \u1f36 + '0')。 在 Scala 2.9 中,£ 现在报告为 illegal character(可能是规范中的正确行为)。 § 字符也无效。任何想法为什么?

以上是关于Scala 中的有效标识符字符的主要内容,如果未能解决你的问题,请参考以下文章

Scala基础:变量字符串数据类型常量和标识符

Scala shell 中的垃圾收集

Scala-变量和数据类型

scala学习笔记——操作符

★Java语法——————————标识符

在 spark/scala 中给出重复值唯一标识符