書いて覚えるSwift入門

第24回 型の探求

この記事を読むのに必要な時間:およそ 4 分

型がないなら作ればいいのに

しかしそれではJSONのような入れ子があるデータはどうしたらよいのでしょう? 答えは単純。そのような型を作ってしまえばよいのです。たとえば[Int]を入れ子にしたいとしたら,

enum NestedArray<Element> {
    case V(Element)
    case A([NestedArray])
}

という型を宣言しておいてから,

var na = NestedArray.A([
    NestedArray.V(0),
    NestedArray.V(1),
    NestedArray.A([
        NestedArray.V(2),
    NestedArray.V(3)
    ])
])

と書けばおk……って何これ長い!

もちろん,もっと短くも書けます。

var na:NestedArray = .A([
    .V(0), .V(1), .A([.V(2), .V(3)])
])

あらかじめ型を宣言しておけば,その中の要素の種類は省略してこのように書けてしまいます。しかし中の値にどうやってアクセスすれば?

ここから本格的な型作りが始まります。

まずは手始めに中の値にアクセスできるようにしてみましょう。

extension NestedArray {
    var value:Element? {
        switch self {
        case let .V(v):
            return v
        default:
            return nil
        }
    }
    var array:[NestedArray]? {
        switch self {
        case let .A(a):
            return a
        default:
            return nil
        }
    }
}

これを実行すると次のようになります。

na.array?[0].value // 0
na.array?[1].value // 1
na.array?[2].value // nil
na.array?[2].array?[0].value // 2

どうやらうまくいったようです。

でも,本来配列なのに.arrayで中身を取り出さなければならないなんておかしいですよね?

添字で直接中身を読み書きできない?

extension NestedArray {
    subscript(i:Int)->NestedArray? {
        get {
        switch self {
        case let .A(a):
            return a[i]
        default:
            return nil
        }
        }
        set {
            switch self {
            case var .A(a):
                a[i] = newValue!
                self = .A(a)
            default:
                return
            }
        }
    }
}

これも実行すると,次のような結果が表示されます。

na[0]?.value // 0
na[1]?.value // 1
na[2]?.value // nil
na[2]?[0]?.value // 2
na[0] = .V(42)
na[0]?.value // 42
na[1]?.value // 1

直接.map()できない? そのままforループにかけられない? いっそきちんとしたSequenceになるまで発展させられない?

―あとは読者の宿題ということで。

このような感じで必要な機能をextensionに追加していくのが,Swiftにおける「型作り」になります。

次号予告

ところで今回作ったNestedArrayは,Intだけではなく,DoubleStringでもいけます。

var nad:NestedArray = .A([
    .V(0.0), .V(1.1), .A([.V(2.2), .V(3.3)])
])

var nas:NestedArray = .A([
    .V("zero"), .V("one"), .A([.V("two"), .V("three")])
])

とくにそう宣言していないのになぜそれができたのでしょうか?

ところでSwiftにはAnyというなんでも入る型がすでに存在しています。

var a:Any = [0,1,[2,3]]

結論から先に言うと,Anyは避けるべきです。少なくとも,動的言語の変数のように使うべきでありません。しかし,その理由はいったいなぜなのか?

次回はこれらの疑問に答えつつ,Swiftの型の核心に迫っていきます。

Software Design

本誌最新号をチェック!
Software Design 2017年10月号

2017年9月16日発売
B5判/192ページ
定価(本体1,220円+税)

  • 第1特集
    個人でも会社でも使える!
    これだけは知っておきたいGitのキホン
  • 第2特集
    システムのセキュリティチェックをもっと楽に
    脆弱性スキャナVuls入門
  • 一般記事
    サーバーレスで実現!
    素材集サービスを効率化した自動画像管理システムに学ぶ
  • 一般記事
    スキルアップの傾向と対策
    ネットワークエンジニア その技術の極め方
  • 一般記事
    telnetを武器にシステムの本質を理解する
    身近なメールで使われている技術をネットワークコマンドで体験してみよう

著者プロフィール

小飼弾(こがいだん)

1969年生まれ,東京都出身。元ライブドア取締役の肩書きよりも,最近はPokemon GOのガチトレーナーのほうが有名になりつつある……かもしれない永遠のエンジニアオヤジ。

活躍の場はIT業界だけでなく,サブカルからアカデミックまで多方面にわたり,ネットからの情報発信は気の向くまま毎日毎秒! https://twitter.com/dankogai,ニコニコチャンネルは,http://ch.nicovideo.jp/dankogai,blogはhttp://blog.livedoor.jp/dankogai/

当社刊行書籍は『小飼弾のアルファギークに逢ってきた』『小飼弾のコードなエッセイ』など。他にも著書多数。

コメント

コメントの記入