枚举类型

枚举类型定义了一个其值由指定的值组成的新类型,这些值是有序的。例如:

  1. type
  2. Direction = enum
  3. north, east, south, west

以下情况成立:

  1. ord(north) == 0
  2. ord(east) == 1
  3. ord(south) == 2
  4. ord(west) == 3
  5. # 也允许:
  6. ord(Direction.west) == 3

由此可知,north < east < south < west。比较运算符可以与枚举类型一起使用。枚举值也可以使用它所在的枚举类型来限定,如 north 可以用 Direction.nort 来限定。

为了更好地与其他编程语言连接,可以显式为枚举类型字段分配序数值,但是,序数值必须升序排列。未明确给出序数值的字段被赋予前一个字段 +1 的值。

显式有序枚举可以有 间隔 :

  1. type
  2. TokenType = enum
  3. a = 2, b = 4, c = 89 # 可以有间隔

但是,它不再是序数,因此不可能将这些枚举用作数组类型的索引。 过程 inc , dec, succ 和 pred 对于它们不可用。

编译器支持内置的字符串化运算符 $ 用于枚举。字符串化的效果是,显式控制要使用的字符串:

  1. type
  2. MyEnum = enum
  3. valueA = (0, "my value A"),
  4. valueB = "value B",
  5. valueC = 2,
  6. valueD = (3, "abc")

从示例中可以看出,可以通过使用元组指定字段的序数值以及字符串值,也可以只指定其中一个。

枚举可以使用 pure 编译指示进行标记,以便将其字段添加到特定模块特定的隐藏作用域,只在最终使用时进行查询。 只有不产生歧义的符号才会添加到此作用域。但总是可以通过 MyEnum.value 类型限定来获取:

  1. type
  2. MyEnum {.pure.} = enum
  3. valueA, valueB, valueC, valueD, amb
  4. OtherEnum {.pure.} = enum
  5. valueX, valueY, valueZ, amb
  6. echo valueA # MyEnum.valueA
  7. echo amb # 错误: 不确定它是 MyEnum.amb 还是 OtherEnum.amb
  8. echo MyEnum.amb # OK.

枚举值的名称是可重载的,就像例程。如果枚举 T 和 U 都有一个名为 foo 的成员,那么标识符 foo 要在 T.foo 和 U.foo 之间二选一。在重载解析过程中, foo 的最终类型由上下文决定。如果 foo 的类型不明确,将产生静态错误。

  1. type
  2. E1 = enum
  3. value1,
  4. value2
  5. E2 = enum
  6. value1,
  7. value2 = 4
  8. const
  9. Lookuptable = [
  10. E1.value1: "1",
  11. # 不需要再修饰value2,已经知道是E1.value2。
  12. value2: "2"
  13. ]
  14. proc p(e: E1) =
  15. # 在 'case' 语句中消除歧义。
  16. case e
  17. of value1: echo "A"
  18. of value2: echo "B"
  19. p value2

在某些情况下,枚举的歧义取决于当前作用域与枚举定义所在作用域之间的关系。

  1. # a.nim
  2. type Foo* = enum abc
  3. # b.nim
  4. import a
  5. type Bar = enum abc
  6. echo abc is Bar # true
  7. block:
  8. type Baz = enum abc
  9. echo abc is Baz # true

对于用枚举实现位域,请查看位域部分。