3.6 符号
符号为原子值,其打印形式类似于一个带有 ' 的标识符。 以 ' 开头,后跟一个标识符的的表达式会产生一个符号值。
> 'a 'a
> (symbol? 'a) #t
对于任何字符序列,都只有一个对应的符号被保留(interned); 调用过程 string->symbol 或通过 read 读取语法标识符, 都会产生保留的符号。由于保留符号可简单地通过 eq?(eqv? 或 equal? 亦可)来比较, 因此它们可方便地作为标签和枚举值来使用。
符号是区分大小写的。通过使用 #ci 前缀或其它方式, 可以让读取器将字符序列的大小写归一(case-fold)来得到一个符号, 不过读取器默认会保留大小写。
> (eq? 'a 'a) #t
> (eq? 'a (string->symbol "a")) #t
> (eq? 'a 'b) #f
> (eq? 'a 'A) #f
> #ci'A 'a
任何字符串(即任何字符序列)均可通过应用 string->symbol 来得到对应的符号。 对于读取器的输入来说,除空白符和以下特殊符号之外,均可直接出现在标识符中:
( ) [ ] { } " , ' ` ; # | \
实际上,# 只是不允许作为符号开头,且不允许紧跟在 % 之后。 其它情况下 # 也可以使用。. 本身并不是一个符号。
通过 | 或 \ 引述的方式,空白符或特殊符号也可被包含在标识符中。 这种引述机制会在标识符的打印形式中包含特殊字符,或看起来像数值时使用。
> (string->symbol "one, two") '|one, two|
> (string->symbol "6") '|6|
The Racket Reference的Reading Symbols一节中阐述了符号语法的要点。
函数 write 在打印符号时不会有 ' 前缀。符号的 display 形式与其对应的字符串相同。
过程 gensym 和 string->uninterned-symbol 会生成一个全新的 未保留(uninterned)符号,该符号(按照 eq?) 不等于任何前面的已保留或未保留的符号,未保留符号通常用作不会与其它值混淆的全新标签。
> (define s (gensym)) > s 'g42
> (eq? s 'g42) #f
> (eq? 'a (string->uninterned-symbol "a")) #f
The Racket Reference的Symbols一节中提供了关于符号的更多信息。