今更ながらSwift5の変更点について調べました（標準ライブラリ編）

#前置き

ども。この間4.2にあげたばかりと思ってたらもう5とか出てますよ…じゃああげようかなと思っていたんですが、通信ライブラリ（Alamofire）のXcode10.2&Swift5の正式対応は5.x以降らしくまだbeta版しかなかった（2019/10/4時点）ので一旦断念しました。。。😭
ライブラリの互換性はとっても大事ですので事前に確認しましょう❗️❗️

#本題

忘れないためにも自分で調べながら理解をするのが一番だと思っているので一つずつ自分なり解釈していこうと思います。
出来るだけわかりやすく書くつもりですが個人的見解なので間違いがあるかもしれません。
見つけたらご指摘いただけると幸いです🙇‍♂️


では早速公式のプログから変更点を調べていこうと思います。

[[公式ブログ：Swift 5 Released!]](https://swift.org/blog/swift-5-released/)

目玉は**ABI（Application Binary Interface）安定**でSwiftのライブラリが今後のmacOSやiOS、tvOS、watchOSの全てのバージョンに含まれることにより、アプリのビルドが容易になり、サイズも小さくなるとのこと。

#文字列リテラル
[[SE-0200]](https://github.com/apple/swift-evolution/blob/master/proposals/0200-raw-string-escaping.md)
文字列リテラルは、拡張区切り文字（#）を使用して表現できるようになったとのこと。

```swift
// swift4.2
let hoge = "The \"rain" in \"Spain\" falls mainly on the Spaniarsd."

// swift 5
let hoge = #"The "rain" in "Spain" falls mainly on the Spaniarsd."#
```

少ないタイピングで済むのはいいことです！
では、少し突っ込んで実際に使うときのQ&Aです。

- Q1）変数を埋め込むには？

　A）\＃()で変数を囲む。

```swift
let answer = 42
let dontpanic = "The answer to life, the universe, and everthing is \#(answer)."
```


- Q2）#を埋め込むには？

　A）##で文字列リテラルを囲む。

```swift
let hoge = ##"My dog "woof"#gooddog"##
```

- Q3）複数行の文字列は？

　A）#"" で始まって ""#で終わる。

```swift

let multiline = #""The answer to life,
the universe,
and everythubg is \#(answer).""#
```

と言う感じです。覚えればなんてことないですね。


#Unicodeプロパティの追加
[[SE-0211]](https://github.com/apple/swift-evolution/blob/master/proposals/0211-unicode-scalar-properties.md)
Unicode.Scalarにプロパティが追加されてます。
isMathとかisEmojiとか使えそうですね。

```swift
  public var isAlphabetic: Bool { get }    // Alphabetic
  public var isASCIIHexDigit: Bool { get }    // ASCII_Hex_Digit
  public var isBidiControl: Bool { get }    // Bidi_Control
  public var isBidiMirrored: Bool { get }    // Bidi_Mirrored
  public var isDash: Bool { get }    // Dash
  public var isDefaultIgnorableCodePoint: Bool { get }    // Default_Ignorable_Code_Point
  public var isDeprecated: Bool { get }    // Deprecated
  public var isDiacritic: Bool { get }    // Diacritic
  public var isExtender: Bool { get }    // Extender
  public var isFullCompositionExclusion: Bool { get }    // Full_Composition_Exclusion
  public var isGraphemeBase: Bool { get }    // Grapheme_Base
  public var isGraphemeExtend: Bool { get }    // Grapheme_Extend
  public var isHexDigit: Bool { get }    // Hex_Digit
  public var isIDContinue: Bool { get }    // ID_Continue
  public var isIDStart: Bool { get }    // ID_Start
  public var isIdeographic: Bool { get }    // Ideographic
  public var isIDSBinaryOperator: Bool { get }    // IDS_Binary_Operator
  public var isIDSTrinaryOperator: Bool { get }    // IDS_Trinary_Operator
  public var isJoinControl: Bool { get }    // Join_Control
  public var isLogicalOrderException: Bool { get }    // Logical_Order_Exception
  public var isLowercase: Bool { get }    // Lowercase
  public var isMath: Bool { get }    // Math
  public var isNoncharacterCodePoint: Bool { get }    // Noncharacter_Code_Point
  public var isQuotationMark: Bool { get }    // Quotation_Mark
  public var isRadical: Bool { get }    // Radical
  public var isSoftDotted: Bool { get }    // Soft_Dotted
  public var isTerminalPunctuation: Bool { get }    // Terminal_Punctuation
  public var isUnifiedIdeograph: Bool { get }    // Unified_Ideograph
  public var isUppercase: Bool { get }    // Uppercase
  public var isWhitespace: Bool { get }    // Whitespace
  public var isXIDContinue: Bool { get }    // XID_Continue
  public var isXIDStart: Bool { get }    // XID_Start
  public var isCaseSensitive: Bool { get }    // Case_Sensitive
  public var isSentenceTerminal: Bool { get }    // Sentence_Terminal (S_Term)
  public var isVariationSelector: Bool { get }    // Variation_Selector
  public var isNFDInert: Bool { get }    // NFD_Inert
  public var isNFKDInert: Bool { get }    // NFKD_Inert
  public var isNFCInert: Bool { get }    // NFC_Inert
  public var isNFKCInert: Bool { get }    // NFKC_Inert
  public var isSegmentStarter: Bool { get }    // Segment_Starter
  public var isPatternSyntax: Bool { get }    // Pattern_Syntax
  public var isPatternWhitespace: Bool { get }    // Pattern_White_Space
  public var isCased: Bool { get }    // Cased
  public var isCaseIgnorable: Bool { get }    // Case_Ignorable
  public var changesWhenLowercased: Bool { get }    // Changes_When_Lowercased
  public var changesWhenUppercased: Bool { get }    // Changes_When_Uppercased
  public var changesWhenTitlecased: Bool { get }    // Changes_When_Titlecased
  public var changesWhenCaseFolded: Bool { get }    // Changes_When_Casefolded
  public var changesWhenCaseMapped: Bool { get }    // Changes_When_Casemapped
  public var changesWhenNFKCCaseFolded: Bool { get }    // Changes_When_NFKC_Casefolded
  public var isEmoji: Bool { get }    // Emoji
  public var isEmojiPresentation: Bool { get }    // Emoji_Presentation
  public var isEmojiModifier: Bool { get }    // Emoji_Modifier
  public var isEmojiModifierBase: Bool { get }    // Emoji_Modifier_Base
```

#DictionaryLiteralのリネーム
[[ SE-0214]](https://github.com/apple/swift-evolution/blob/master/proposals/0214-DictionaryLiteral.md)
DictionaryLiteralの型がKeyValuePairに変更になった。名前もKeyValuePairsになりました。エイリアスで旧名称も残っていますが、KeyValuePairsを使いましょう。

#Never型の拡張
[[ SE-0215]](https://github.com/apple/swift-evolution/blob/master/proposals/0215-conform-never-to-hashable-and-equatable.md)
Never型はEquatableとHashableを適合するように変更。

```swift
extension Never: Equatable {
  public static func == (lhs: Never, rhs: Never) -> Bool {
    switch (lhs, rhs) {
    }
  }
}

extension Never: Hashable {
  public func hash(into hasher: inout Hasher) {
  }
}
```

>※知らない人（私を含むw）の為にNever型とは？
>**インスタンスを持たない型**です**Voidではありません**。
>インスタンスを持たないのでメソッドの戻り値では**返せない**です。
>こちらの記事がとってもわかりやすいと思います！
>[SwiftのNeverとボトム型 / Never as a Bottom Type](https://speakerdeck.com/hironytic/never-as-a-bottom-type?slide=16)

この特性をうまく生かした例が[提案者の記事](https://nshipster.com/never/)に具体的に示されています。

#compactMapValues追加
[[ SE-0218]](https://github.com/apple/swift-evolution/blob/master/proposals/0218-introduce-compact-map-values.md)

DictionaryにcompactMapValuesが追加されたとのこと。
簡単にいうとDictionaryのValueの型変換や、nilの除去が行えるとのこと。

```swift
let d: [String: String?] = ["a": "1", "b": nil, "c": "3"]
let r4 = d.compactMapValues({$0})
// r4 == ["a": "1", "c": "3"]
もしくは
let d: [String: String] = ["a": "1", "b": "2", "c": "three"]
let r5 = d.compactMapValues(Int.init)
// r5 == ["a": 1, "b": 2]
```

#Characterにpropertyが追加
[[ SE-0221]](https://github.com/apple/swift-evolution/blob/master/proposals/0221-character-properties.md)

```swift
public  var isASCII ： Bool { ... }
public  var asciiValue ： UInt8 ？{ ... }
public  var isWhitespace ： Bool { ... }
public  var isNewline ： Bool { ... }
public  var isNumber ： Bool { ... }
public  var isWholeNumber ： Bool { ... }
public  var wholeNumberValue ： Int ？{ ... }
public  var isHexadecimalDigit ： Bool { ... }
public  var decimalDigitValue ： Int ？{ ... }
public  var isLetter ： Bool { ... }
public func uppercased() -> String { ... }
public func lowercased() -> String { ... }
public var isUppercase: Bool { ... }
public var isLowercase: Bool { ... }
public var isCased: Bool { ... }
public var isSymbol: Bool { ... }
public var isMathSymbol: Bool { ... }
public var isCurrencySymbol: Bool { ... }
public var isPunctuation: Bool { ... }
```
各funcの説明は省略しますが、名前からある程度推測できそうですね。

#isMultiple（of :)の追加
[[ SE-0225]](https://github.com/apple/swift-evolution/blob/master/proposals/0225-binaryinteger-iseven-isodd-ismultiple.md)

ある数が別の数の倍数であるかどうかを確認するメソッドですね。

```swift
let number = 8
if number.isMultiple(of: 2) {
    print("isEven")
} else {
    print("isOdd")
}
```

#StringInterpolationの拡張
[[ SE-0228]](https://github.com/apple/swift-evolution/blob/master/proposals/0228-fix-expressiblebystringinterpolation.md)
Swift 5 ではStringInterpolationがカスタマイズできるようになったとのこと。

```swift
// extensionを追加して

public extension String.StringInterpolation {
    /// Interpolates a date using the supplied formatter.
    ///
    /// - Parameters:
    ///   - value: a date
    ///   - formatter: a date formatter
    mutating func appendInterpolation(_ value: Date, _ formatter: DateFormatter) {
        appendLiteral(formatter.string(from: value))
    }
}

public extension DateFormatter {
    /// Returns an initialized `DateFormatter` instance using the
    /// supplied date and time styles.
    ///
    /// - Parameters:
    ///   - date: a date style
    ///   - time: a time style
    /// - Returns: an initialized date formatter using the current locale
    static func format(date: Style, time: Style) -> DateFormatter {
        let formatter = DateFormatter()
        formatter.locale = Locale.current
        (formatter.dateStyle, formatter.timeStyle) = (date, time)
        return formatter
    }
}


// ・・・使用例
let hoge: Date = Date()
let formatter = DateFormatter.format(date: .medium, time: .medium)
print("date:\(hoge, formatter)")
```
というようなことができるようになるみたいです。幅が広がりますね。
その他のサンプルは[こちら](https://github.com/erica/SwiftInterpolation/tree/master/SwiftInterpolation)に色々記載がありました。

#SIMDVectors追加
[[ SE-0229]](https://github.com/apple/swift-evolution/blob/master/proposals/0229-simd.md)
SIMD(Single Instruction Multiple Data)プログラミングをより快適に行うための改良のようです。

```swift

public protocol SIMDScalar {
  associatedtype SIMDMaskScalar : SIMDScalar & FixedWidthInteger & SignedInteger
  associatedtype SIMD2Storage : SIMDStorage where SIMD2Storage.Scalar == Self
  associatedtype SIMD4Storage : SIMDStorage where SIMD4Storage.Scalar == Self
  associatedtype SIMD8Storage : SIMDStorage where SIMD8Storage.Scalar == Self
  associatedtype SIMD16Storage : SIMDStorage where SIMD16Storage.Scalar == Self
  associatedtype SIMD32Storage : SIMDStorage where SIMD32Storage.Scalar == Self
  associatedtype SIMD64Storage : SIMDStorage where SIMD64Storage.Scalar == Self
}

public protocol SIMDStorage {
  /// The type of scalars in the vector space.
  associatedtype Scalar : Hashable

  /// The number of elements in the vector.
  var scalarCount: Int { get }

  /// A vector with zero or the default value in all lanes.
  init()

  /// Element access to the vector.
  subscript(index: Int) -> Scalar { get set }
}

public protocol SIMD : SIMDStorage, Hashable, CustomStringConvertible {
  associatedtype MaskStorage : SIMD
    where MaskStorage.Scalar : FixedWidthInteger & SignedInteger
}
```
・・・正直あまりピンときてないので、使う機会があったら詳しく調べてみようと思いますww


#標準ライブラリのプロトコルから4つのカスタマイズポイントを削除
[[ SE-0232]](https://github.com/apple/swift-evolution/blob/master/proposals/0232-remove-customization-points.md)
翻訳したものをそそまま転記しますwww

標準ライブラリのプロトコルから4つのカスタマイズポイントを削除します。
・map、filterおよびforEachからSequence
・first、 prefix(upTo:)、prefix(through:)、及びsuffix(from:)からCollection
・last オン BidirectionalCollection
これらのシンボルのデフォルトの実装はそのままであるため、シーケンスとコレクションは、現在と同じ操作を引き続き使用できます。

目的は
・動作の違いを考慮します。
・より効率的な実装を可能にします。
とのこと。

#Numericプロトコルの修正
[[ SE-0233]](https://github.com/apple/swift-evolution/blob/master/proposals/0233-additive-arithmetic-protocol.md)

Numericプロトコルの定義間違いを修正するために新しいプロトコルAdditiveArithmeticが導入されました。
Numericの動作と要件はそのまま維持しているとのことです。

```swift
public protocol AdditiveArithmetic: Equatable {
  /// A zero value.
  static var zero: Self { get }

  /// Adds two values and produces their sum.
  ///
  /// The addition operator (`+`) calculates the sum of its two arguments. For
  /// example:
  ///
  ///     1 + 2                   // 3
  ///     -10 + 15                // 5
  ///     -15 + -5                // -20
  ///     21.5 + 3.25             // 24.75
  ///
  /// You cannot use `+` with arguments of different types. To add values of
  /// different types, convert one of the values to the other value's type.
  ///
  ///     let x: Int8 = 21
  ///     let y: Int = 1000000
  ///     Int(x) + y              // 1000021
  ///
  /// - Parameters:
  ///   - lhs: The first value to add.
  ///   - rhs: The second value to add.
  static func + (lhs: Self, rhs: Self) -> Self
  
  /// Adds two values and stores the result in the left-hand-side variable.
  ///
  /// - Parameters:
  ///   - lhs: The first value to add.
  ///   - rhs: The second value to add.
  static func += (lhs: inout Self, rhs: Self) -> Self
  
  /// Subtracts one value from another and produces their difference.
  ///
  /// The subtraction operator (`-`) calculates the difference of its two
  /// arguments. For example:
  ///
  ///     8 - 3                   // 5
  ///     -10 - 5                 // -15
  ///     100 - -5                // 105
  ///     10.5 - 100.0            // -89.5
  ///
  /// You cannot use `-` with arguments of different types. To subtract values
  /// of different types, convert one of the values to the other value's type.
  ///
  ///     let x: UInt8 = 21
  ///     let y: UInt = 1000000
  ///     y - UInt(x)             // 999979
  ///
  /// - Parameters:
  ///   - lhs: A numeric value.
  ///   - rhs: The value to subtract from `lhs`.
  static func - (lhs: Self, rhs: Self) -> Self
  
  /// Subtracts the second value from the first and stores the difference in the
  /// left-hand-side variable.
  ///
  /// - Parameters:
  ///   - lhs: A numeric value.
  ///   - rhs: The value to subtract from `lhs`.
  static func -= (lhs: inout Self, rhs: Self) -> Self
}

public extension AdditiveArithmetic where Self : ExpressibleByIntegerLiteral {
  public  static  var zero ： Self {
    return  0
  }
}
```


#Subsequenceのレスポンス改善と型消失の解消
[[ SE-0234]](https://github.com/apple/swift-evolution/blob/master/proposals/0234-remove-sequence-subsequence.md)

どういうことかものすごーくザックリいうと、

```swift
func dropFirst(_:) -> SubSequence
func dropLast(_:) -> SubSequence
func drop(while:) -> SubSequence
func prefix(_:) -> SubSequence
func prefix(while:) -> SubSequence
func suffix(_:) -> SubSequence
func split(separator:) -> [SubSequence]
```
上記のメソッドにはデフォルト実装として、AnySquence<Element>を返す実装が行われているので型消去が発生し結果レスポンスの悪化に繋がっているとのことです。

>*AnySequenceって？わからない方はこちら[AnySequenceってなんなの？](http://quesera2.hatenablog.jp/entry/2016/05/03/234721)の記事が大変参考になると思います。
> javaやC#経験者ならとても理解しやすいと思います。

今回はこれを解消するためSequenceを拡張したとのことです。

```swift
struct Enumerated<Base: Sequence> {
  let _base: Base
}
extension Sequence {
  func enumerated() -> Enumerated<Self> {
    return Enumerated(_base: self)
  }
}
```

```swift
extension Enumerated: Sequence {
  typealias Element = (Int,Base.Element)
  struct Iterator: IteratorProtocol {
    var _count: Int
    let _base: Base.Iterator
    mutating func next() -> Element? {
      defer { _count += 1 }
      return _base.next().map { (_count,$0) }
    }
  }
  func makeIterator() -> Enumerated<Base>.Iterator {
    return Iterator(_count: 0, _base: _base.makeIterator())
  }
}
```

```swift
extension Enumerated: Collection where Base: Collection {
  struct Index: Comparable {
    let _count: Int, _base: Base.Index
    static func < (lhs: Index, rhs: Index) -> Bool {
      return lhs._base < rhs._base
    }
  }
  var startIndex: Index { return Index(_count: 0, _base: _base.startIndex) }
  var endIndex: Index { return Index(_count: Int.max, _base: _base.endIndex) }
  subscript(i: Index) -> Element {
    return (i._count, _base[i._base])
  }
}
```

#Resultがswiftの標準として取り込まれた
[[ SE-0235]](https://github.com/apple/swift-evolution/blob/master/proposals/0235-add-result.md)
エラーハンドリングでお馴染みのResultです。
外部のライブラリを使わなくてよくなりますね。

```swift
public enum Result<Success, Failure: Error> {
    case success(Success), failure(Failure)
}
```

#withContiguous{Mutable}StorageIfAvailableメソッド導入
[[ SE-0237]](https://github.com/apple/swift-evolution/blob/master/proposals/0237-contiguous-collection.md)
もともとあったメソッド

```swift
_withUnsafeMutableBufferPointerIfSupported
```
を

```swift
withContiguousMutableStorageIfAvailable
```
として公開しSequenceとMutableCollectionのプロトコルに追加したとのこと。
Sequence.withContiguousStorageIfAvailable
MutableCollection.withContiguousMutableStorageIfAvailable
これらが使用できることにより一部のアルゴリズム（ソートなど）で大幅な高速化を実現できるとのこと。

#RangeにCodableの適合を追加
[[ SE-0239]](https://github.com/apple/swift-evolution/blob/master/proposals/0239-codable-range.md)
適合するのは

- Range
- ClosedRange
- PartialRangeFrom
- PartialRangeThrough
- PartialRangeUpTo

でRengeでencodeが使えるようになります。これは使う時が来るかもですね。
１つ注意事項として挙げられているのが独自のCodableを定義している場合に
コンパイラエラーが発生する（重複した準拠として）ので、その場合はラップしてくださいとのこと。

```swift
// ラップのサンプル

public struct MyRangeWrapper<Bound>
    where Bound: Comparable {
    public var range: Range<Bound>
}


extension MyRangeWrapper {
    enum CodingKeys: CodingKey {
        case lowerBound
        case upperBound
    }
}

extension MyRangeWrapper: Decodable
where Bound: Decodable {
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let lowerBound = try container.decode(Bound.self, forKey: .lowerBound)
        let upperBound = try container.decode(Bound.self, forKey: .upperBound)
        self.range = lowerBound ..< upperBound
    }
}
```

#String.indexのencodedOffsetをDeprecateに
[[ SE-0241]](https://github.com/apple/swift-evolution/blob/master/proposals/0241-string-index-explicit-encoding-offset.md)

[SE-0180](https://github.com/apple/swift-evolution/blob/master/proposals/0180-string-index-overhaul.md)の意図された目的に従っておらずencodedOffsetが誤用で使用されており潜在的なバグを引き起こす可能性があるのでDeprecateにするのが目的みたいです。
バグフィックスはまだ対策が打たれていないため今後対策が検討されるようです。

#終わりに
以上、長くなりましたが色々調べてみると言語が出来上がっていく背景が少しずつ見えてきて面白かったです。
言語のコードとかなかなか見る機会はないかもですが勉強になるので時間があったらみてみることをお勧めします❗️❗️❗️

次は[追加関数とコンパイラの変更点](https://qiita.com/ikuo-yamashita/items/9b9ec04cb4bde189ded3)について調べたいと思います。ではでは👋

#参考
大変勉強になりました！ありがとうございます🙇‍♂️

- [What’s new in Swift 5](https://medium.com/@d_date/whats-new-in-swift-5-70225f063b87)
- [SwiftのNeverとボトム型 / Never as a Bottom Type](https://speakerdeck.com/hironytic/never-as-a-bottom-type?slide=16)