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 ReferenceReading Symbols一节中阐述了符号语法的要点。

函数 write 在打印符号时不会有 ' 前缀。符号的 display 形式与其对应的字符串相同。

例如:
> (write 'Apple)

Apple

> (display 'Apple)

Apple

> (write '|6|)

|6|

> (display '|6|)

6

过程 gensymstring->uninterned-symbol 会生成一个全新的 未保留(uninterned)符号,该符号(按照 eq?) 不等于任何前面的已保留或未保留的符号,未保留符号通常用作不会与其它值混淆的全新标签。

例如:
> (define s (gensym))
> s

'g42

> (eq? s 'g42)

#f

> (eq? 'a (string->uninterned-symbol "a"))

#f

+The Racket ReferenceSymbols一节中提供了关于符号的更多信息。