元组

元组和你目前见到的对象很像。它们是赋值时拷贝每个组成部分的值类型。与对象类型不同的是,元组类型是结构化类型,这意味着不同的元组类型是 等价的 如果它们以相同的顺序指定相同类型和相同名称的字段。

构造函数 () 可以用来构造元组。构造函数中字段的顺序必须与元组定义中的顺序匹配。但与对象不同,此处可能不使用元组类型的名称。

如对象类型, t.field 用来访问一个元组的字段。 另一个对象不可用的标记法是 t[i] 访问第 i' 个字段。这里 i 必须是一个常整数。

  1. type
  2. # 类型表示一个人:
  3. # 一个人有名字和年龄。
  4. Person = tuple
  5. name: string
  6. age: int
  7.  
  8. # 等价类型的语法。
  9. PersonX = tuple[name: string, age: int]
  10.  
  11. # 匿名字段语法
  12. PersonY = (string, int)
  13.  
  14. var
  15. person: Person
  16. personX: PersonX
  17. personY: PersonY
  18.  
  19. person = (name: "Peter", age: 30)
  20. # Person和PersonX等价
  21. personX = person
  22.  
  23. # 用匿名字段创建一个元组:
  24. personY = ("Peter", 30)
  25.  
  26. # 有匿名字段元组兼容有字段名元组。
  27. person = personY
  28. personY = person
  29.  
  30. # 通常用于短元组初始化语法
  31. person = ("Peter", 30)
  32.  
  33. echo person.name # "Peter"
  34. echo person.age # 30
  35.  
  36. echo person[0] # "Peter"
  37. echo person[1] # 30
  38.  
  39. # 你不需要在一个独立类型段中声明元组。
  40. var building: tuple[street: string, number: int]
  41. building = ("Rue del Percebe", 13)
  42. echo building.street
  43.  
  44. # 下面的行不能编译,它们是不同的元组。
  45. #person = building
  46. # --> Error: type mismatch: got (tuple[street: string, number: int])
  47. # but expected 'Person'

即使你不需要为元组声明类型就可以使用,不同字段名创建的元组将认为是不同的对象,尽管有相同的字段类型。

元组只有在变量赋值期间可以 解包 。 这方便将元组字段直接一个个赋值给命名变量。一个例子是 os module 模块中的 splitFile 过程, 它同时返回一个路径的目录、名称和扩展名。元组解包必须使用小括号括住你想赋值的解包变量,否则你将为每个变量赋同样的值!例如:

  1. import os
  2.  
  3. let
  4. path = "usr/local/nimc.html"
  5. (dir, name, ext) = splitFile(path)
  6. baddir, badname, badext = splitFile(path)
  7. echo dir # 输出 `usr/local`
  8. echo name # 输出 `nimc`
  9. echo ext # 输出 `.html`
  10. # 下面输出同样的行:
  11. # `(dir: usr/local, name: nimc, ext: .html)`
  12. echo baddir
  13. echo badname
  14. echo badext

元组字段总是公有的,你不必像对象类型字段显式的标记来导出。