Skip to content

Instantly share code, notes, and snippets.

@norio-nomura
Last active November 23, 2016 23:23
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save norio-nomura/e6cf04cfc1cb940e61ac651da22d7593 to your computer and use it in GitHub Desktop.
Save norio-nomura/e6cf04cfc1cb940e61ac651da22d7593 to your computer and use it in GitHub Desktop.
SequenceType を使った Swift 2.2 のコードを Swift 3 に書き換えて、Swift 2.2でもビルド可能にする。

SequenceType を使った Swift 2.2 のコードを Swift 3 に書き換えて、Swift 2.2でもビルド可能にする。

次のSwift 2.2コードをSwift 3でビルドできるようにする。

//
//  SequenceTests.swift
//
import XCTest

class SequenceTests: XCTestCase {
    func testExample() {
        XCTAssertTrue(contain([1, 2])([1, 2]))
        XCTAssertFalse(contain([2, 3])([1, 2]))
    }
}

extension SequenceType {
    func all(predicate: Generator.Element -> Bool) -> Bool {
        return reduce(true) { $0 && predicate($1) }
    }
}

func contain<S: SequenceType, T: Equatable where S.Generator.Element == T>(items: [T]) -> S -> Bool {
    return { sequence in
        sequence.all(items.contains)
    }
}

Swift 3での変更
SequenceTypeSequence
SequenceType.GeneratorSequence.Iterator
単純に書き直すと

@@ -10,13 +10,13 @@ class SequenceTests: XCTestCase {
     }
 }
 
-extension SequenceType {
-    func all(predicate: Generator.Element -> Bool) -> Bool {
+extension Sequence {
+    func all(predicate: Iterator.Element -> Bool) -> Bool {
         return reduce(true) { $0 && predicate($1) }
     }
 }
 
-func contain<S: SequenceType, T: Equatable where S.Generator.Element == T>(items: [T]) -> S -> Bool {
+func contain<S: Sequence, T: Equatable where S.Iterator.Element == T>(items: [T]) -> S -> Bool {
     return { sequence in
         sequence.all(items.contains)
     }

typealias を使う

Swift 3 の Sequence で書いておいて、Swift 2.2の場合 SequenceType となるように typealiase を書くと Swift 2.2 と 3 の両方でビルドできるコードになるのでは? typealias を書いてみると

#if !swift(>=3)
    typealias Sequence = SequenceType
    typealias Sequence.Iterator = SequenceType.Generator
#endif

ビルドエラー

SequenceTests.swift:27:23: expected '=' in typealias declaration  
 
   typealias Sequence.Iterator = SequenceType.Generator  
                     ^  

associatedtype が指定できない。

protocol を作る

ならば protocol Sequence を定義。

#if !swift(>=3)
    public protocol Sequence: SequenceType {
        associatedtype Iterator: GeneratorType = Generator
    }
#endif

ビルドエラー

SequenceTests.swift:15:29: cannot convert value of type '(_, Self.Iterator.Element) -> Bool' to expected argument type '(Bool, _) -> Bool'

        return reduce(true) { $0 && predicate($1) }
                       ^

どうやら S.Generator.Element: Equatable の制約がつかず、元の

extension SequenceType where Generator.Element: Equatable {
    func contains(element: Self.Generator.Element) -> Bool
}

ではなく、こちら

extension SequenceType {
    func contains(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool
}

になってしまう。

protocol を作り、基本APIのオーバーライドを用意する。

IteratorGenerator が同じものとみなすオーバーライドしたメソッドを用意するといける。

#if !swift(>=3)
    public protocol Sequence: SequenceType {
        associatedtype Iterator: GeneratorType = Generator
    }

    extension Array: Sequence {}

    extension Sequence {
        internal func reduce<T>(initial: T, @noescape combine: (T, Iterator.Element) throws -> T) rethrows -> T {
            return try reduce(initial) { (prevResult, element: Generator.Element) -> T in
                try combine(prevResult, element as! Iterator.Element)
            }
        }
    }
#endif
//
// SequenceTests.swift
//
import XCTest
class SequenceTests: XCTestCase {
func testExample() {
XCTAssertTrue(contain([1, 2])([1, 2]))
XCTAssertFalse(contain([2, 3])([1, 2]))
}
}
extension Sequence {
func all(predicate: Iterator.Element -> Bool) -> Bool {
return reduce(true) { $0 && predicate($1) }
}
}
func contain<S: Sequence, T: Equatable where S.Iterator.Element == T>(items: [T]) -> S -> Bool {
return { sequence in
sequence.all(items.contains)
}
}
#if !swift(>=3)
public protocol Sequence: SequenceType {
associatedtype Iterator: GeneratorType = Generator
}
extension Array: Sequence {}
extension Sequence {
internal func reduce<T>(initial: T, @noescape combine: (T, Iterator.Element) throws -> T) rethrows -> T {
return try reduce(initial) { (prevResult, element: Generator.Element) -> T in
try combine(prevResult, element as! Iterator.Element)
}
}
}
extension Sequence where Generator: Equatable, Iterator == Generator {
internal func contains(element: Iterator.Element) -> Bool {
return contains(element)
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment