2016-04-08 4 views
1

コンテキスト:私はオブジェクトのジェネリックスタックを持っています。次のオプションがあるまで、リピート動作を繰り返し、それ以外の場合はエラー オプションですが、何かが含まれていればアンラップします

  • を投げ、スタックは、(オプションを返す))(ポップに応答し、私は、スタックが空の場合、スタック

    • を処理する必要がある機能を持っていますunwrappableない
    • これまで

    guard var nextVar = myStack.pop() else { 
        throw MyError.EmptyStack 
    } 
    
    repeat { 
        // Process nextVar 
    } while nextVar = myStack.pop() 
    

    問題:最初のNextVarはオプションではありませんので、私の中の呼び出しが失敗します。どのように書き換えることができるので、whileはオプションに何かが含まれているかどうかをチェックし、成功すれば変数にコンテンツを割り当てますか? ()

  • 答えて

    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 
    } 
    

    popGeneratorType.next()の正確必要な実装であるので、(generate()selfを返すことによって)GeneratorTypeSequenceTypeにこれを有効にする簡単なはずです。

    は値型であるため、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 
        } 
    } 
    
    +1

    マイナー発言:あなたはSequenceType *と* generatorTypeを両方を採用した場合、あなたは(生成実装する必要はありません)、デフォルトの実装があります。 –

    関連する問題