exercise_03.md 4.2 KB
Newer Older
G
update  
guenchi 已提交
1 2
# 标志符

G
update  
guenchi 已提交
3
Scheme对标识符的宽容度远大于其他语言,你可以在标识符里使用大多数符号,可以重写所有的系统预留关键字,但仍有一些符号严格禁止使用在标志符里。
G
update  
guenchi 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

在Scheme里它们大多数是预留的读取器宏。

> 读取器宏是一种在编译前对代码进行替换的工具,你可以将它看作高级版的C语言宏。在Scheme的近亲语言,Common Lisp里你可以自由的编写读取器宏。在Scheme的世界里读取器宏被视作邪恶而混乱的,只预留了少量程序语言标准层面的读取器宏来简化程序编写。

```
#                    
```

编译器预留符号, 它用来表示字符,比如`#\a #\b #\c`。用来表示进制数,比如`#b100 #x7C0`,用来表示向量,比如`#(1 2 3)`。用来表示编译器行为钩子,比如`(#3%display "Hello,World!")`在ChezScheme中表示强制用第三级优化火力全开的display hello world。

```
'     单引号
```
读取器宏,`'object`将在编译前被替换成`(quote object)`。它也用来表示列表,如`'(a b c)`. 

> 在Scheme中,quote有重要的作用,它代表标志符的符号的一面。而不被quote住的标志符代表它作为程序的一面。LISP与其他程序语言最大的区别即是代码即是数据,数据即是代码。在这种情况下我们必须明确一个标志符在当下是否被自动进行求值。即它对编译器展现它名字的一面,还是它程序的一面。这个区别便由quote来表示。 

```
`    往右斜的单引号
```
G
guenchi 已提交
25
读取器宏,`` `object ``将在编译前被替换成`(quasiquote object)`
G
update  
guenchi 已提交
26 27 28 29 30 31 32 33 34

```
,     逗号
```
读取器宏,`,object`将在编译前被替换成`(unquote object)`

```
@  
```
G
guenchi 已提交
35 36
读取器宏,`,@object`将在编译前被替换成`(unquote-splicing object)`

G
update  
guenchi 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
在Scheme规定中`@`只是不能出现在标致符的开头。但实际使用中,含`@`的标志符会导致太多问题。比如,在标志符尾部的`@`有可能影响读取器对右括号的读取。所以这里尽量建议不要在标志符中使用`@`


```
.
```
`.`在scheme程序中起到表示"对"的作用。比如(a . b)。它不能使用在标识符的开头。

```
+
-
```
`+``-`因为需要表示数学格式,所以不能出现在标志符的开头。

*特例*

```
->
```
`->`组合在标志符开头是合法的。


G
update  
guenchi 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
> 可以使用在标识符里的字符有:`? ! . + - * / < = > : $ % ^ & _ ~`。比起记住它们,更好的办法是记住那些禁止使用的字符。


以下的代码风格并不由编译器严格要求,但是它能帮助你更好的编写Scheme程序,还有助于其他人更好的阅读你的代码。

*** 使用短-连接标识符词组 ***

在Scheme惯例中我们不使用驼峰命名法或者下划线。在此我特别不建议使用下划线连接词组。因为当你的Scheme程序需要链接C模块时,C程序将和Scheme程序共享命名空间。这个时候用`a-c-program`来包装C语言的`a_c_program`就显得特别一目了然。

*** 全大写标识符表示常量 ***

继承自C程序的常量表示法是个良好的习惯。在Scheme里没有常量,但至少你应该知道它禁止更改。

*** 用三个 * 号包围的标识符表示全局变量 ***

当看见如`***value***`包裹的全局变量,在引入有副作用的过程时就需要三思。

*** 标识符用后缀?表示返回布尔值 ***

`char?` `list?` 这些过程都返回布尔值。

*** 标识符用!后缀表示过程有副作用 ***

`set!`表示它改变了指针指向的某些值,虽然它的返回有可能是布尔值。

*** 标识符用->表示类型转换 ***

请记住Scheme是强类型语言,在惯例中,我们使用`->`来表示从左边的类型转换到右边的类型。比如`list->vector`

*** 用两个空格缩进 ***

因为有时需要嵌套两个左空格`(`,有且仅有使用两个空格的缩进才会不让你的缩进乱了套。

*** 用空格对齐选择的分支 ***

在选择的分支,填充多余的空格来让分支对齐。而不是只使用两个空格。
```
(if test? 
    consequent
    alternative)

(cond ((clause1 ...) (do ...))
      ((clause2 ...) (do ...))
      ...
      (else ...))
```