# 语法与块:读懂一段 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。