Swift:为什么在这种情况下CustomStringConvertible描述运行次数太多?

时间:2016-07-22 14:59:58

标签: swift swift-playground

我在Xcode Playground中尝试使用此代码时注意到description getter方法被调用了太多次。

代码在这里:https://gist.github.com/T-Pham/4b72d17851162a32b2fc534f0618135d

首先使用print行,代码运行3176次。

enter image description here

然后在第一个print注释掉的情况下,代码运行3164次。

enter image description here

这意味着第一个print必须运行代码12次。 然而,

enter image description here

它是148次。

1 个答案:

答案 0 :(得分:4)

这是操场上弄乱你的头。

Playground正在计算自己对具有CustomStringConvertibe协议的变量的调用(可能是为了在右侧面板上提供信息)。

如果您只是调用镜像(树)而根本不打印,则可以看到这种情况。

如果使用自己的计数器计算实际调用次数,则会产生非常不同的结果:

 var descCount = 0
 extension Node: CustomStringConvertible {
     var description: String 
     {
         descCount += 1
         return "id: \(id)\nleft: \(left)\nright: \(right)"
     }
 }

 descCount = 0
 print(tree)
 descCount   // 12

 descCount = 0
 print(mirror(tree))
 descCount   // 12 

顺便说一句,我在理解mirror()函数时遇到了一些麻烦,我认为递归的函数可能更容易理解。如何向Node添加mirror()函数:

 func mirror() -> Node
 {
    let result = Node()
    result.id      = id
    result.left    = right?.mirror()
    result.right   = left?.mirror()
    return result
 }

 print(tree.mirror())

[编辑]这里是一个非递归镜像函数(与你的逻辑逻辑相同),结构更清晰:

 func mirror2(tree:Node) -> Node
 {
    // will return top of mirrored tree
    let newTree = Node()

    // node pair used for traversal and duplication
    var original:Node! = tree
    var mirrored:Node! = newTree

    // traversal of tree structure left side first
    // (uses mirrored tree to keep track of traversed nodes)
    while original != nil
    {
       // carry node identifier (and contents eventually)
       mirrored.id = original.id 

       // downwards, mirror left side first (if not already done)
       if (original.left == nil) != (mirrored.right == nil)
       {
          original       = original.left
          mirrored.right = Node()
          mirrored       = mirrored.right 
          continue     
       }

       // downwards, mirror right side second (if not already done)
       if (original.right == nil) != (mirrored.left == nil)
       {
          original      = original.right
          mirrored.left = Node()
          mirrored      = mirrored.left
          continue
       }

       // upwards from leaves and completed branches
       original = original.parent
       mirrored = mirrored.parent
    }
    return newTree
 }

和树形描述的一些视觉糖果:

 extension Node: CustomStringConvertible 
 {
     var indent:String 
     { return "  " + (parent?.indent ?? "") }
     var description: String 
     {
         return "\(id)\n"
              + ( left  != nil ? "\(indent)L:\(left!)" : "" )
              + ( right != nil ? "\(indent)R:\(right!)" : "" )
     }
 }

可以更轻松地比较结果:

 print(tree)

 // 0
 //   L:1
 //     L:3
 //       L:7
 //       R:8
 //     R:4
 //       L:9
 //       R:10
 //   R:2
 //     R:6
 //       L:13
 //       R:14
 //

 print(mirror2(tree))

 //  0
 //    L:2
 //      L:6
 //        L:14
 //        R:13
 //    R:1
 //      L:4
 //        L:10
 //        R:9
 //      R:3
 //        L:8
 //        R:7