82 lines
2.8 KiB
Markdown
82 lines
2.8 KiB
Markdown
# 语法与块:读懂一段 Smalltalk
|
||
|
||
> 原书依据:第 4 章,印刷页 13–20,PDF 页 24–31。赋值和返回符号按导读约定规范化。
|
||
|
||
## 先识别字面量
|
||
|
||
| 写法 | 含义 |
|
||
| --- | --- |
|
||
| `42`、`16rFF`、`2.5` | 整数、十六进制整数、浮点数 |
|
||
| `$A` | 字符 |
|
||
| `'Ada'` | 字符串 |
|
||
| `'it''s'` | 包含单引号的字符串 |
|
||
| `#size`、`#at:put:` | 符号,常用于表示选择子 |
|
||
| `#(2 4 6)` | 字面量数组 |
|
||
| `[ :x | x + 1 ]` | 接受参数的块 |
|
||
|
||
`nil`、`true`、`false`、`self`、`super` 是具有特殊语义的伪变量,不能按普通局部变量赋值。不要把字符串 `'size'` 与符号 `#size` 混用。
|
||
|
||
## 三种消息与优先级
|
||
|
||
一元消息没有参数;二元消息接受一个参数;关键词消息通过带冒号的片段标出参数位置。`at:put:` 是一个选择子。
|
||
|
||
优先级为:**括号内表达式 → 一元消息 → 二元消息 → 关键词消息**。同级按从左到右处理,二元选择子没有传统乘除优先的规则。
|
||
|
||
```smalltalk
|
||
2 + 3 * 4 "推演为 20"
|
||
2 + (3 * 4) "推演为 14"
|
||
10 raisedTo: 2 + 3 "等价于 10 raisedTo: (2 + 3)"
|
||
```
|
||
|
||
`a at: 1 put: 9` 是一条消息。两个关键词调用连续出现时,用括号明确哪一个结果作为另一个的参数。
|
||
|
||
## 句点与分号
|
||
|
||
句点分隔表达式;分号让消息继续发给同一个接收者。
|
||
|
||
```smalltalk
|
||
| values |
|
||
values := OrderedCollection new.
|
||
values add: 4; add: 9; add: 16.
|
||
values size
|
||
```
|
||
|
||
这里三次 `add:` 的接收者都是 `values`。若要在一段级联表达式末尾取得集合本身,可发送 `yourself`:
|
||
|
||
```smalltalk
|
||
OrderedCollection new
|
||
add: 4;
|
||
add: 9;
|
||
yourself
|
||
```
|
||
|
||
## 块把计算推迟
|
||
|
||
```smalltalk
|
||
| square |
|
||
square := [ :n | n * n ].
|
||
square value: 6
|
||
```
|
||
|
||
创建块不执行块体;`value:` 传入参数并求值,预期结果是 36。无参数块接收 `value`,两个参数可用 `value:value:`。
|
||
|
||
控制流也可以用消息与块组织:
|
||
|
||
```smalltalk
|
||
| count total |
|
||
count := 1.
|
||
total := 0.
|
||
[count <= 4] whileTrue: [
|
||
total := total + count.
|
||
count := count + 1].
|
||
total
|
||
```
|
||
|
||
推演结果为 10。条件块每轮重新求值;把条件提前算成单个布尔对象,会失去更新后的判断。`ifTrue:ifFalse:` 则把两段待执行的分支交给布尔对象选择。
|
||
|
||
## 返回的边界
|
||
|
||
块通常返回最后一个表达式的值。方法若没有 `^` 显式返回,则默认返回接收者。块中的 `^` 涉及从其所属方法返回,不能简单理解成普通函数局部 return。本文示例避免把含非局部返回的块保存到方法退出之后;需要这样的用法时,应核对目标镜像的块实现。
|
||
|
||
练习:`3 + 4 factorial` 先执行哪条消息?先向 4 发送 `factorial`,再向 3 发送 `+`;按数学结果推演为 27。
|