虽然是可选的,但如果包含某些内容则展开

时间:2016-04-08 14:25:19

标签: swift do-while

上下文:我有一个通用的对象堆栈。堆栈响应pop()(返回一个可选项),我有一个需要处理堆栈的函数

  • 如果堆栈为空,则抛出错误
  • 否则,重复重复操作直到下一个选项不可解决

到目前为止

guard var nextVar = myStack.pop() else {
   throw MyError.EmptyStack
}

repeat {
    // Process nextVar
} while nextVar = myStack.pop()

问题:第一个nextVar不是可选的,因此我的while调用失败。如何重写以便while检查可选项是否包含某些东西,如果成功,则将内容分配给变量? ()

1 个答案:

答案 0 :(得分:3)

您应该修改堆栈类型以包含isEmpty属性。然后,您无需复制pop调用,这将是一个简单的while-let循环。

guard !myStack.isEmpty else {
   throw MyError.EmptyStack
}

while let nextVar = myStack.pop() {
    // Process nextVar
}

您也可以将其转换为SequenceType,但迭代不会消耗堆栈。那就是:

guard !myStack.isEmpty else {
   throw MyError.EmptyStack
}

for nextVar in myStack {
    // Process nextVar
}

由于pop正是GeneratorType.next()所需的实现,因此应该很容易将其转换为GeneratorTypeSequenceType(通过返回selfgenerate())。

但是由于Stack是一个值类型,用for-in迭代它会生成一个副本然后使用该副本,而不是消耗原始堆栈。这可能是好事还是坏事。

这是我的意思草图:

struct Stack<Element> {
    private var stack: [Element] = []
    mutating func push(element: Element) {
        stack.append(element)
    }

    mutating func pop() -> Element? {
        guard let result = stack.last else { return nil }
        stack.removeLast()
        return result
    }

    var isEmpty: Bool { return stack.isEmpty }
}

extension Stack: GeneratorType {
    mutating func next() -> Element? {
        return pop()
    }
}

extension Stack: SequenceType {
    func generate() -> Stack {
        return self
    }
}