【问题标题】:Swift struct type recursive valueSwift struct 类型递归值
【发布时间】:2016-12-11 15:38:38
【问题描述】:

结构体在 Swift 中不能有递归值类型。所以下面的代码无法在 Swift 中编译

struct A {
    let child: A
}

值类型不能递归,因为它的大小是无限的。但是我想知道为什么下面的代码可以编译?

struct A {
    let children: [A]
}

【问题讨论】:

  • 子元素可以是空数组
  • 数组是一个结构体,但它不直接保存它的值。
  • 如果包含的 ref.是可选的..

标签: swift recursion struct


【解决方案1】:

如果您知道 Node 永远只有一个父级(如果 leaf),那么您可以像这样使用 enum 和 indirect case

public enum Node<Value> {
    case root(value: Value)
    indirect case leaf(parent: Node, value: Value)
}

public extension Node {
    var value: Value {
        switch self {
        case .root(let value): return value
        case .leaf(_, let value): return value
        }
    }
}

如果你知道你的节点总是有两个父节点,你可以调整枚举大小写以适应它,等等。

【讨论】:

    【解决方案2】:

    数组不直接保存它的值。数组本质上是一个结构,它保存对包含项目的外部内存块的引用。因此所有的数组都占用相同的内存量,在结构体中使用没有问题。

    演示:

    struct Value {
        var array: [Int] = [] 
    }
    
    var value = Value()
    value.array = [0, 1, 2, 3]  // this won't increase the size of the struct!
    

    如果数组的行为不同,您将无法动态更改它们的大小(例如附加元素)或使用它们的写时复制行为。本质上,数组和字典是包装成值类型的类。

    因此,您的代码可以编译,因为它不是真正的递归。

    【讨论】:

      【解决方案3】:

      我认为这是关于所需的空间。

      无限空间

      创建这种类型的值

      struct A {
          let child: A
      }
      

      我们需要

      • 当前结构的空间
      • 孩子的空间
      • 孩子的孩子的空间
      • ...

      所以我们需要无限空间

      有限空间

      另一方面是创造这个价值

      struct A {
          let children: [A]
      }
      

      我们只需要

      • A 的空间
      • Array的空间。

      【讨论】:

        【解决方案4】:

        由于 child[] 可以为空,因此没有理由不这样做。这编译得很好:

        struct Foo {
          let child: [Foo]
        }
        
        let foo = Foo(child: [Foo(child:[Foo(child:[]), Foo(child:[])])])
        

        虽然我看不出它有什么实际用途——不过我想知道是否有。

        【讨论】:

        • 您的回答已经有一段时间了,但我找到了它的实际用途。目前正在修补具有另一种参考货币值的 Currency 结构。
        猜你喜欢
        • 2016-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多