【问题标题】:Swift recursive enum enters infinite loop in constructorSwift递归枚举在构造函数中进入无限循环
【发布时间】:2016-03-16 22:03:09
【问题描述】:

我在 Swift 中创建了一个递归 enum,它编译时没有错误或警告,但是当我尝试实例化它时会进入无限循环:

enum Tree<T> {
    case Leaf(T)
    case Branch(T, [Tree<T>])
}

Tree.Leaf(0) // enters infinite loop
Tree.Branch(0, []) // enters infinite loop

无限循环发生在实例化时,而不是在打印或对实例的任何其他使用时。即使没有对结果进行任何处理,Tree.Leaf(0) 仍然会永远运行。需要明确一点:无限循环发生在运行时,而不是编译时,而是在实例化时立即发生。

奇怪的是,以下非常相似的数据结构可以完美运行:

enum WorkingTree<T> {
    case Leaf(T)
    case Branch([WorkingTree<T>]) // notice the lack of a `T` in this case
}

WorkingTree.Leaf(0) // works fine
WorkingTree.Branch([.Leaf(1), .Leaf(2)]) // works fine

也许更奇怪的是,以下数据结构完美地工作:

enum ConcreteTree {
    case Leaf(Int)
    case Branch(Int, [ConcreteTree])
}

ConcreteTree.Leaf(0) // works fine
ConcreteTree.Branch(0, []) // works fine

为什么我的原始数据结构在我尝试实例化时会进入无限循环,而其他几乎相同的数据结构却没有?

编辑:

在 Swift REPL 中,问题似乎取决于实例化是否发生在与类型声明相同的“块”中。如果我在 Swift REPL 中输入以下内容:

1> enum Tree<T> {
2.     case Leaf(T)
3.     case Branch(T, [Tree<T>])
4. } // press enter, declare type
5> Tree.Leaf(0) // separate command to the REPL

然后它会因无限循环而失败。但是,如果我将它们作为同一语句的一部分输入:

1> enum Tree<T> {
2.     case Leaf(T)
3.     case Branch(T, [Tree<T>])
4. } // press down arrow, continue multiline command
5. Tree.Leaf(0) // part of the same command

那么就不会进入死循环,按预期工作。

会发生什么?

编辑 2

事情变得更加奇怪了。以下代码编译运行,但在一个非常意外的地方进入了无限循环:

enum Tree<T> {
    case Leaf(T)
    case Branch(T, [Tree<T>])
}

let test = Tree.Leaf(0)
print("Milestone 1") // prints

switch test {
    case .Leaf(_): print("Milestone 2") // prints
    default: print("This should never be called")
}

func no_op<T>(x: T) {}

no_op(test) // infinite loop entered here
print("Milestone 3") // DOES NOT print

no_op(Tree.Leaf(0))
print("Milestone 4") // DOES NOT print

什么可能会将无限循环推迟到no_op 调用?

【问题讨论】:

    标签: swift recursion enums infinite-loop recursive-datastructures


    【解决方案1】:

    你忘了说indirect

    enum Tree<T> {
        indirect case Leaf(T)
        indirect case Branch(T, [Tree<T>])
    }
    

    我有点惊讶于没有它编译的代码;我建议提交错误报告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      • 2011-08-20
      相关资源
      最近更新 更多