Swift中的递归枚举的奇怪行为(Beta 7)

时间:2014-09-03 20:58:50

标签: swift

enum Tree{
    case Leaf(String)
    case Node(Tree)
} //compiler not happy!!

enum Tree{
    case Leaf(String)
    case Node([Tree])
} //compiler is happy in (arguably) a more complex recursive scenario?

Swift编译器如何处理第二个(更复杂的)场景而不是第一个?

3 个答案:

答案 0 :(得分:10)

值得注意的是Swift 2 beta 2并且还具有递归枚举的indirect关键字 - 这意味着

enum Tree<T> {
    case Leaf(T)
    indirect case Node(Tree)
}

是有效的语言构造,在Swift 2中不会破坏模式匹配。

TL;决定的DR:&#34; [...]我们认为正确的解决方案是不通过枚举来支持一般的,非显而易见的递归,并要求程序员用间接的方式明确地调解它。&# 34;

答案 1 :(得分:3)

值类型(枚举)不能将自身包含为直接成员,因为无论数据结构有多大,它都不能包含自身。枚举案例的显然关联数据被认为是枚举的直接成员,因此关联数据不能是枚举本身的类型。 (实际上,我希望它们能够使递归枚举工作;对于功能数据结构来说它会非常棒。)

但是,如果你有一个间接级别,那就没关系。例如,关联数据可以是对象(类的实例),该类可以具有枚举的成员。由于类类型是引用类型,它只是一个指针而不直接包含对象(因而也就是枚举),所以它很好。

您的问题的答案是:[Tree]不直接包含Tree成员。 Array的字段是私有的,但我们通常可以推断出数组元素的存储没有直接存储在Array结构中,因为这个结构对于给定的{{{{{}}具有固定的大小。 1}},但数组可以有无限数量的元素。

答案 2 :(得分:1)

3 *}

Apple开发者论坛上的Chris Lattner(Swift设计师)says
  

已经成为一种在参考文献中“封装”表达值的方法(例如   解决递归枚举的限制。)

但是,以下代码(适用于Swift 1.1)在Xcode Beta版本6.3(6D520o)附带的Swift 1.2中不起作用。错误消息是“属性只能应用于声明,而不是类型”,但是如果这是预期的,我不知道如何将它与Lattner关于他在前面引用中谈到的行为的声明进行协调是“有用的”事情,我们还没有用Swift 1.2删除它。“

enum BinaryTree {
    case Leaf(String)
    case Node(@autoclosure () -> BinaryTree, @autoclosure () -> BinaryTree)
}

let l1 = BinaryTree.Leaf("A")
let l2 = BinaryTree.Leaf("B")
let l3 = BinaryTree.Leaf("C")
let l4 = BinaryTree.Leaf("D")
let n1 = BinaryTree.Node(l1, l2)
let n2 = BinaryTree.Node(l3, l4)
let t = BinaryTree.Node(n1, n2)