Swiftのリテラルについて
インターン先でSwiftの言語仕様について学ぶ機会があり、その中でリテラル
について学んだので少し理解を深掘りたいと思っています。
リテラルについて
まず、この記事を書くにあたり、リテラルについて調べてみる事にしました。
hoge := "abc"
これをみた時、hogeはString型
である事がわかります。
僕たち人間は、このhogeをStringだと見ただけでわかりますが、機械ではこれを判断出来ません。
しかし、リテラルを用いる事で、値からそれがどの型なのかを自動的に推測しています。
Swiftのリテラル
Swiftでも、Int, Double, String, Character, Unicode, Bool, Optional, Array, Dictionaryのリテラルを提供しています。
https://nshipster.com/swift-literals/
let a = "abc" //String let b = 1 // Integer let c = true // Boolean
Optional
は、someとnoneの2つのケースが用意されているenumです。
しかし、Optional型と宣言しておけば、nil
と文字を与えるだけでOptional型と推測されます。
let d: Optional<String> = nil
ExpressibleByNilLiteral
これは、Optional型がExpressibleByNilLiteral
を継承しているからです。
nilリテラル nil
を使用して初期化できる型と書かれています。
https://developer.apple.com/documentation/swift/expressiblebynilliteral
public enum Optional<Wrapped> : ExpressibleByNilLiteral { case none case some(Wrapped) public init(nilLiteral: ()) }
Optional以外で、ExpressibleByNilLiteral
を使うことは非推奨で、SwiftではOptional
とImplicitlyUnwrappedOptional
および`_OptionalNilComparisonType`にのみ使用されています。
応用で使ってみると以下のようになります
struct Nilable: ExpressibleByNilLiteral { init(nilLiteral: ()) {} } let a: Nilable = nil
Nilableかたで、nilを型推論を使って宣言する事ができます。
少し応用したものを書いてみました
enum HogeHoge { case none case success(String) case failure } extension HogeHoge: ExpressibleByNilLiteral { public init(nilLiteral: ()) { self = .none } } extension HogeHoge: ExpressibleByStringLiteral { init(stringLiteral value: StringLiteralType) { if value.count >= 8 { self = .success(value) } else { self = .failure } } } let a: HogeHoge = nil let b: HogeHoge = "1234" let c: HogeHoge = "12345678" print(a) // none print(b) // failure print(c) // success("12345678")
ExpressibleByStringLiteral
とExpressibleByNilLiteral
を使う事で、Validation機能を持った型を作成しました。
このように、リテラルの種類は決めれらていますが、Protocolを使う事でいろんな型をコントロールする事ができます。
まとめ
当たり前のように型推論を使っていましたがなぜという所に立ち戻ると、今回のようなリテラル
のようなProtocolを使って実装されている事がわかりました。