Chill 语言中,信息处理的基本单位是 数据(Data)。 数据是信息在计算机中的一种表示。
在Chill语言中,数据可以表示为能直接被语法分析器解析的 字面量(Literal),如:
5 ; 数值
"S" ; 字符串
T ; 布尔真
F ; 布尔假
nil ; 空值
:sym ; 符号量
也可以借助字面量从而表示成一种组合的 结构(Structure):
(new Point 5 6) ; 表示二维点的二元组
(new (Array Int 5) 0) ; 表示定长为5,全部元素为 0 的 Int数组
又可以引用、存储抑或间接引用 在识别为 标识符(Identifier) 的变量中:
(let a 5) ; 动态变量 a 引用了 数据5, 通过使用 a 来使用 a 所引用的数据
(dim b Int) ; 声明了一个 类型为Int的 静态变量 b
(set b 5) ; 静态变量 b 存储了 数据5
(ref c a) ; 引用变量 c 引用了 变量a, c 间接引用了 a 的数据。 同时 a 的变化会直接反映到 c
甚至可以储存于 存储空间(Memory Space) 中,通过地址来访问:
(new-ptr Number 0x00010cab) ; 将首地址为0x00010cab的一段数据视为Number数据并获取之
表达式(Expression) 是一种由关键词、变量和数据等组成的,带有一定结构的、可运算的式子。
如同许多 Lisp 方言,Chill 语言 的表达式是一种前缀记法。如:
(+ 5 6)
(? T 5 6)
有所不同的是,Chill 语言中,在一个表达式中,必须有置于开头的函数或操作符。
当表达一个纯数据的列表时,使用 (list ...)
来处理。如:
(list 1 2 3)
(list (+ 5 6) a)
(list (list 5) 6)
为了方便起见,可以使用 [...]
来替代 (list ...)
,如:
[1 2 3]
[(+ 5 6) a]
[[5] 6]
通常,表达式是立即求值的。意即,在使用了嵌套表达式的情况下,外层表达式运算时,必然已经得到了内层表达式的值。
如 (+ 5 (+ 6 (+ 7 8)))
的求值顺序:
(+ 5 (+ 6 (+ 7 8)))
(+ 5 (+ 6 15))
(+ 5 21)
26
这一点在条件表达式、迭代表达式等中是例外。 条件表达式的子式、迭代表达式的循环式 都是惰性求值的。详细见后续内容。
值得一提的是,Chill 语言只规定了 外层 和 内层 的求值顺序。在同一层的表达式之间,其求值顺序是未定义的。
如 (+ 5 (+ 7 2) (+ 3 6))
只保证在求 最外层 的时候内层计算全部完成,而 (+ 7 2)
和 (+ 3 6)
的先后顺序是未定义的。
有时,需要将多个表达式组成为一个表达式。这个时候使用 do 表达式 。 如:
(do
(+ 5 6)
(+ 1)
5
)
do 表达式的值为从上到下计算各个表达式后,最后一个表达式的值。
如果直接使用 (do)
,则表示空式。其值为 nil
。
do 表达式 经常用于某些特殊表达式的子式中。 如 ? 表达式 等。
动态变量(Dynamic Variable) 是一种使用自由的数据携带者。
动态变量的着重点在于,通过直接对数据的 引用(refer) 而便利地、安全地处理数据。
使用 let
可以使动态变量引用某个数据。
(let a 5) ; 令 a 引用 数据 5
通常情况下,直接使用动态变量的名字,可以表示该动态变量所引用的数据。
(+ a 5) ; 使用了 a 所引用的数据,根据之前的代码,a 表示 数据 5
一个自由的动态变量可以引用任何被允许引用的数据。
(let a 5) ; 引用了 数据5
(let b (new (Array Int 5))) ; 引用了 一个新建的定长5的Int数组
(let c b) ; 引用了 a 所引用的数据
(dim stvarb Int) ; 声明一个静态变量,静态变量拥有特有空间
(let c stvarb) ; 引用了这个静态变量的空间
[?] 动态变量的唯一操作是引用 let
。
动态变量不能直接改变其引用空间的数据,但可以通过一些空间修改的函数,来改变其引用空间数据的部分。
(let a [5 6 7]) ; a 引用了一个列表
(set a 0 3) ; 将 a 引用的列表的首元素设置为 3,此时 a 所引用的数据为 [3 6 7]