Sway 参考手册/数组和列表
Sway 内置了三种主要的数据结构:数组、列表和对象。数据结构只是一个信息位[1]集合,它们以某种方式粘合在一起形成一个整体。这些位中的每一个都可以单独访问。通常,这些位之间也存在某种关系,因此数据结构是将所有这些相关位打包在一起的便捷方式。
数组是一种数据结构,它具有以下属性:每个信息位都可以像其他位一样快速访问。要创建数组,可以使用array函数
var a = array(42,64.0,"hello",:world);
此调用将创建一个数组,将四个项目或元素打包在一起。变量a被创建并设置为指向该包。
要访问单个元素,可以使用“方括号”表示法或“点”表示法。例如,以下是如何访问数组中的第一个项目
sway> a[0]; INTEGER: 42 sway> a . 0 INTEGER: 42
注意,数组索引(方括号之间或点后的数字称为索引)是从零开始的。也就是说,第一个元素位于索引 0,第二个元素位于索引 1,依此类推。通常,由于“点”的高优先级,不会将“点表示法”用于数组。例如
a[row * cols + col]
与以下内容不同
a . row * cols + col
在后者中,检索row索引处的元素,然后乘以cols,最后将该数字加到col。为了使后者与前者相同,需要对索引计算进行括号化
a . (row * cols + col)
使用方括号表示法,括号化会自动执行。
也可以对数组进行赋值
sway> a[0] = :forty-two; SYMBOL: :forty-two sway> a[0]; SYMBOL: :forty-two
您也可以查看数组的尾部。数组的尾部是没有第一个元素或头部元素的数组。
sway> tail(a); ARRAY: [64.000000000,"hello",:world] sway> tail(a)[0]; REAL_NUMBER: 64.000000000
如果不断取数组的尾部,最终会得到:null:
sway>tail(tail(tail(tail(a)))); SYMBOL: :null;
可以分配一个数组,而无需指定实际元素
var b = alloc(10);
这将创建一个包含十个元素的数组(索引范围从零到九)。
sway> b[0]; SYMBOL: :null;
每个元素都初始化为 :null。
列表是一种数据结构,它具有以下属性:可以通过在列表中的任何位置添加或删除元素来延长或缩短它。这种灵活性的折衷方案是,列表中较后面的元素比较前面的元素需要更长时间访问。创建和访问列表中的元素与数组非常相似
var a = list(42,64.0,"hello",:world); sway> a[2]; STRING: "hello" sway> a[3] = 13; INTEGER: 13
要使列表变长,可以轻松地将一个元素添加到现有列表的前面,以创建一个新列表
var b = "apple" join a; LIST: ("apple",42,64.000000000,"hello",:world)
需要注意的是,上面的a和b共享元素,对a的更改将影响b
sway> a[1] = :pie; SYMBOL: :pie sway> a; LIST: (42,:pie,"hello",:world); sway> b; LIST: ("apple",42,:pie,"hello",:world);
使b独立于a是一项看起来比实际更简单的任务。以下是一个尝试执行此操作的函数
function join*(item,items) { function copy(stuff) { if (stuff == :null,:null,stuff[0] join copy(tail(stuff))); } item join copy(items); }
这在某些情况下有效
var x = list(:apples,:pears,:bananas); var y = :kumquats join* x; //note join*, not join x[1] = :persimmons;
sway> x; LIST: (:apples,:persimmons,:bananas); sway> y; LIST: (:kumquats,:apples,:pears,:bananas);
问题在于,join*进行的复制是浅复制。也就是说,复制了传入的列表,但没有复制元素。对于符号列表,不需要复制元素,但这并非总是如此
var m = list(2,3,4); sway> var p = list(1,m,5); LIST: (1,(2,3,4),5)
sway> var q = 0 join* p; // note, join*, not join LIST: (0,1,(2,3,4),5)
到目前为止,您理解了吗?不仅q共享p的元素,它们还共享m的元素。考虑以下操作
p[1][1] = 333;
我们更改了p的第一个元素的第一个元素
sway> p; LIST: (1,(2,333,4),5) sway> q; LIST: (0,1,(2,333,4),5)
通过p进行的更改仍然更改了q。要解决这个问题,需要进行深复制,其中复制列表的元素,并复制元素的元素,依此类推。
可以使用tail=函数更改列表的尾部
var a = list(1,2,3); a tail= list(222,333);
sway> a; LIST: (1,222,333);
您可以在任何类型的列表上使用tail=,即使是通过tail生成的列表
var b = list(1,2,3); tail(b) tail= list(333);
sway> b; LIST: (1,2,333);
可以使用join、tail和tail=的组合将元素插入列表中间。以下是如何在第一个元素之后插入一个项目
var c = list(1,3,4);
c tail= (3 join tail(c));
sway> c; LIST: (1,2,3,4);
需要括号来确保c的尾部没有设置为数字 3,并且结果与c的尾部连接在一起。
这种插入方法会更改原始列表。也可以通过编写插入函数来创建一个包含插入元素的新列表
function insert(item,items,index) { if (index == 0) { item join items; //put the item at the head of the list } else { items[0] join insert(item,tail(items),index - 1); } }
var d = list(1,3,4); var e = insert(2,d,1); //insert at the second element
sway> d; LIST: (1,3,4);
sway> e; LIST: (1,2,3,4);
请注意,insert组合了插入元素之前的元素的浅复制,并创建了插入元素之后元素的共享。
将在下一章中讨论对象。
- ↑ 非正式意义上的位,而不是零和一。