Array 中存放未知结构动态数据在 Moonbit 怎样表达?

需求就是在一个 Array 当中存放 Trait Object, 满足自己定义的一些接口, 以及一些基础的接口比如 Trait, 不过这样很容易就触发一个报错:

Trait object for AAA is not allowed: Its super trait Eq does not allow objects(4038)

或者:

Trait object for AAA is not allowed: Self occur multiple times in the type of method slow_eq(4038)

之前在 Rust 中要了解到一个写法可以绕过此类问题 dyn_eq - Rust 性能应该还是差的, 但是在需求当中确实存在少量场景需要用来处理用户传入不确定结构的数据, 所以能接受一些性能得退化.

Moonbit 对这种场景有什么建议的写法?

这个限制是必要的,以 Eq 为例,变成 object 之后,== 的签名是 (Eq, Eq) -> Bool。但这样就破坏了原本的实现的 invariant(两个参数的实际类型一样)。

一种办法是给 trait object 加入某种反射,允许从 trait object 反向 down cast。不过目前 MoonBit 的 object 不支持这个功能。

如果需要比较相等的 case 和用户自定义的 case 不重叠的话,可以考虑这样一种办法:不要使用 trait object 而是使用一个 enum,但在 enum 里加一个特殊的 constructor,里面装着一个 trait object。这样一来,已知的情况可以像 enum 一样正常比较相等,未知的情况可以塞进那个 fallback 的 trait object constructor

1 个赞

我的场景数据完全是从 library 外部传入的, enum 方案看上去还是不行了. downcast 方案不目前不可行的话, 还是考虑按照群友建议的用 JsonValue 充当 trait object 绕过已有限制.