4. Lists

4.1 概述

WTCD 允许存储有序不可变列表。其类型名为 list

WTCD 的列表内的元素可以有不同的类型,因此一个长度为 1 的 list 可以被视为是一个可以存储任何类型值的 WTCD 变量。

4.2 创建新的列表

若要创建一个新的列表,请使用 [] 包裹这个列表里的元素。两个元素之间仅需要空格或是换行:

declare list a = [ 1 "Hello" 3 ]

此外,在定义变量时,若使用的类型是 list,并不提供初始值的话,将会默认创建一个空的列表。

declare list empty // []

需要注意的是,这里有一个坑。下述代码:

declare list a = [ 1 -2 3 ]

会被 WTCD 理解为 [ (1 - 2) 3 ]。若要解决这个问题,则需要使用:

declare list a = [ 1 (-2) 3 ]

4.3 获得列表的一个成员

若要获得列表的一个成员,则需要使用成员访问操作符:..??.?.?

4.3.1 普通成员访问

通常来说,访问一个成员使用 . 操作符:

[ "a0" "a1" "a2" "a3" ] . 2 == "a2"
[ "a0" "a1" "a2" "a3" ].(2) == "a2"

由于小数原因,WTCD 不允许直接写 [ "a0" "a1" "a2" "a3" ].2。点与数字之间必须要要用空格隔开,或者用括号把数字包起来。

如果要访问的下标(Index)存在变量里,则可以直接写:

declare number index = 2
[ "a0" "a1" "a2" "a3" ].index == "a2"

需要注意的是,WTCD 的设计提倡“错误尽早发现”,因此当下标不存在(Index out of bounds)或是不正确时,普通成员访问会直接报错。需要注意的是,报错只会在下标不存在时发生。以下例子会正常返回 null

[ "a0" null "a2" ].(1) == null

而这个例子会报错:

[ "a0" "a1" ].(2) // List does not have an element at 2. If return null is desired, use ".?" instead. List contents: list (elements = [string (value = "a0"), string (value = "a1")])

4.3.2 越界即空成员访问

当然,有时候,确实会希望当下标不存在时返回 null。这时候可以使用 .? 来访问成员。

[ "a0" "a1" ] .? (2) == null

需要注意的是,只有下标越界的时候(index < 0 或者 index >= listLength::[list]),.? 才会返回 null。如果提供的下标不是整数依然会报错。(无论如何,你都不应该在下标中使用涉及浮点数运算的操作。)

4.3.3 可选成员访问

还有某些时候,列表本身也可能是 null。如果希望在这个情况下不报错而是直接返回 null,可以使用 ?.

null ?. 2 == null

需要注意的是,?. 是带有 short circuit 的。也就是说,如果左侧计算结果为 null,那么右侧的内容根本不会被计算。

4.3.4 可选越界即空成员访问

如果凑巧,不但你希望在下标越界时返回 null,而且在列表自己是 null 的时候也返回 null,你可以使用 ?.?

null ?.? 2 == null
[ 0 1 2 ] ?.? 3 == null

4.4 改变列表

简而言之,你不能改变列表。

—— 但是你可以从一个列表创建一个稍稍有点不同的列表。

4.4.1 使用标准库函数

最简单的改变列表的方式是使用标准库(见第 6 章)函数(见第 5 章) listSet

declare list a = [ 0 1 2 3 ]
declare list b = listSet::[a 2 "Wow"] // b 是 [ 0 1 "Wow" 3 ]

需要注意的是,正如之前所说,listSet 不会改变列表,你必须把返回值赋给一个之前的或是另一个变量。

declare list a = [ 0 1 2 3 ]

listSet::[a 2 "Wow"]
// a 依然是 [ 0 1 2 3 ]

a = listSet::[a 2 "Wow"]
// a 现在是 [ 0 1 "Wow" 3 ] 了

关于其他改变列表的函数,请前往 6.1

4.4.2 使用 ... 操作符

... 允许用一个数组代替一个新的数组的一部分。

举个例子:

declare list inner = [ 3 4 5 ]
declare list outer = [ 1 2 ...inner 6 7 ] // [ 1 2 3 4 5 6 7 ]

使用 ... 可以获得一个在一个列表的基础上加了若干元素的列表。(添加元素)

declare list a = [ 1 2 3 ]
a = [ ...a "Back" ] // [ 1 2 3 "Back" ]
a = [ "Front" ...a ] // [ "Front" 1 2 3 "Back" ]

或者可以做点别的事情比如:

declare list a = [ 1 2 3 ]
a = [ ...a ...a ] // [ 1 2 3 1 2 3 ]