EffectsOf 编译指示

异常追踪推断规则(见之前的小节)的第一条与第二条确保可以获得下面的预期效果:

  1. proc 我们不抛异常但是回调可能抛(callback: proc()) {.raises: [], effectsOf: callback.} =
  2. callback()
  3. proc 抛异常() {.raises: [IOError].} =
  4. raise newException(IOError, "IO")
  5. proc use() {.raises: [].} =
  6. # 编译失败! 会抛出 IOError 错误!
  7. 我们不抛异常但是回调可能抛(抛异常)

如这个例子所示, proc (…) 类型的参数可以标记为 .effectsOf 。这样的参数带来了 effect 多态: 过程 我们不抛异常但是回调可能抛 可以抛出 callback 所抛出的异常。

所以在很多情况下,回调并不会导致编译器在 effect 分析中过于保守:

  1. {.push warningAsError[Effect]: on.}
  2. import algorithm
  3. type
  4. MyInt = distinct int
  5. var toSort = @[MyInt 1, MyInt 2, MyInt 3]
  6. proc cmpN(a, b: MyInt): int =
  7. cmp(a.int, b.int)
  8. proc harmless {.raises: [].} =
  9. toSort.sort cmpN
  10. proc cmpE(a, b: MyInt): int {.raises: [Exception].} =
  11. cmp(a.int, b.int)
  12. proc harmful {.raises: [].} =
  13. # 无法编译, `sort` 当前将引发异常
  14. toSort.sort cmpE