Poly/ML异常转字符串:直接调用与传参结果不同及代码疑问
问题解答
这是特性,不是Bug
出现这种差异的核心原因是PolyML.makestring对异常的处理依赖于当前作用域中异常构造函数的可见性:
- 直接调用
PolyML.makestring IllegalMove时,IllegalMove是当前作用域明确可见的自定义异常构造函数,makestring能识别它的具体类型,因此输出正确的名称"IllegalMove"。 - 把
IllegalMove传入自定义error函数时,如果该函数的类型签名是exn -> string(或函数定义在异常构造函数不可见的作用域中),异常会被当作通用的exn类型处理。makestring无法从通用exn对象中解析出具体的异常构造函数信息,因此输出默认的"?"。
为什么exnName、exnMessage能正常工作
exnName和exnMessage是PolyML专门提供的异常处理内置函数,它们的设计目标就是绕开作用域限制,直接访问异常对象的元数据:
exnName会直接提取异常的构造函数名称,不管该构造函数在当前作用域是否可见。exnMessage则返回异常的消息内容(如果异常定义时附带了消息),同样不依赖作用域可见性。
举个代码对比例子:
(* 定义自定义异常 *) exception IllegalMove; (* 直接调用,正常输出 *) val direct = PolyML.makestring IllegalMove; (* 结果: "IllegalMove" *) (* 自定义error函数,接收通用exn类型 *) fun error e = PolyML.makestring e; val via_error = error IllegalMove; (* 结果: "?" *) (* 使用exnName处理,正常输出 *) val via_exnName = exnName IllegalMove; (* 结果: "IllegalMove" *)
如果你的error函数需要正确输出异常名称,建议改用exnName实现,而非依赖PolyML.makestring。
内容的提问来源于stack exchange,提问作者Gramps
相关产品推荐
相关产品推荐

