書いて覚えるSwift入門

第15回 文字列の扱い

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

Swiftにおける文字[列]?

ずいぶんと前置きが長くなりました。それではSwiftの文字を実際に見てみましょう。次のコードをplaygroundかREPLで実行してみてください図1⁠。

var str = "Swift"
str += "スウィフト"
str = "\(str)"
let = str
print()

図1 Swiftにおける文字コードの出力結果

図1 Swiftにおける文字コードの出力結果

Swiftスウィフトとprintされたはずです。たった5行のコードでも,これだけのことがわかります。

  • 型宣言は不要。リテラルから適切に推論される
  • ちなみに型の名前はString。Xcodeなら識別子をoption+clickすれば確認できる
  • 文字列リテラルは""で囲まれた内部
  • \()で変数展開(interpolation)
  • 識別子(identifier)にASCII以外のUnicodeを用いることもできる

もっともこのレベルのサポートは,Perl 5.8がもう12年以上前に実現していました。Swiftがすごい――熟練プログラマの多くがやりすぎると感じるかも――のはここからです。次のコードをご覧ください。

let me = "だん"
let me2 = "\u{3060}\u{3093}"
let nfd = "\u{305f}\u{3099}\u{3093}"
me == me2
me == nfd

me == me2trueなのは当然としても,me ==nfdまでもtrueになるのです。なぜ等しいか?

ひらがなの「だ」一文字と「た」+濁点が等しいとSwift(正確にはfunc ==(_:String,_:String)->Boolがみなしているからです。

文字とは何か? 等しい文字とは何か? 文字列を文字にバラして見てみましょう。

for c in "\u{305f}\u{3099}\u{3093}".characters {
    print(c, String(c).unicodeScalars.count, String(c).utf8.count)
}

結果は次のとおりになるはずです。

だ 2 6
ん 1 3

Swiftにおける「文字」=Characterは,1byteではもちろんなく,1 code pointですらなく,1 graphemeなのです。graphemeというのは難しい言葉ですが,OS Xの辞書によると「書記素(書き言葉の最小単位⁠⁠」だそうです。⁠文字列の比較はgraphemeをもってせよ」というのは確かにUnicode Consortiumの文書[tr15]にあるのですが,これをきちんと言語レベルで実装しているのは筆者の知る限りSwiftだけです。

これはある意味,1.0時点でのUnicodeの理念を実現した格好にもなっているのですが,その後Unicodeが現実に対してずいぶん妥協したのは前述のとおりで,実際"ダン" == "ダン"半角カナの" ダン"と全角カナの"ダン" を==で比較してもfalseとなります。

「Unicode潔癖症」?

2.2におけるSwiftの「Unicode潔癖症」は,添字(Subscript)にも見られます。たとえばJavaScriptでは(ES5以降は正式に⁠⁠,

"JavaScript"[4] // "S"

という具合に文字列を文字の配列とみなして文字を取り出すことができますが,

"Swift"[4]

は"t" ではなく(そのままでは)エラーです。だからと言って添字を使えないわけではなく,次のようにすれば似たようなことはできます。

let str = "Swift"
let idx = str.startIndex
str[idx.advancedBy(4)]

これを利用すれば,extensionを使ってIntによる添字を後付けすることは一応できます。

extension String {
    subscript(idx:Int)->Character {
        return self[self.startIndex.advancedBy(idx)]
    }
}
"Swift"[4] // "t"

しかし,デフォルトでそうしようとすればできるのに,今のところはそうなっていません。文字列を文字に分解する際も,わざわざ.charactersというメソッドを経由しています。Swiftに限らずありとあらゆるソフトウェアは理念と現実の狭間にありますが,Swiftの組込み型の中で,文字と文字列の扱いは突出して理念が先行しているように筆者は感じています。

String... the final frontier?

前回「Swiftの'ミステリー'」として,一重引用符''がSwiftではまだ使われていないことを指摘しました。このことはSwiftの現在の文字列の振る舞いに対し,中の人がまだ試行錯誤している証なのかもしれません。実際Swiftの文字列処理は,C/C++/Objective-CよりずっとマシとはいえPerlやRubyはおろか,JavaScriptにも劣るというのが実感です。Swiftの当初の「檜舞台」がモバイルアプリケーション開発であることを考えれば,それでもObjective-Cしかなかったころに比べればずっとマシではあるでしょうし,最悪ややこしい処理はサーバに丸投げしちゃっても良いとはいえ。

しかしオープンソース化され,Linuxにも移植され,サーバサイドでも使われるようになるごく近い将来,現状のSwiftの文字列処理の貧弱さが気がかりです。

裏を返せば,そこが宝の山という見方もできなくもありません。Swiftライブラリで一旗上げるなら,文字列処理を狙うのもよさそうです。

Software Design

本誌最新号をチェック!
Software Design 2022年6月号

2022年5月18日発売
B5判/184ページ
定価1,342円
(本体1,220円+税10%)

  • 第1特集
    シェルの基本大全
    どんな環境でも迷わない・困らない知識
  • 第2特集
    後悔しないAWSデータベースの選び方
    RDSとDynamoDB,使い分けのポイントを徹底解説
  • 第3特集
    不思議の国のSE用語
    一人前のエンジニアになる方法
  • 短期連載
    新生「Ansible」徹底解説
    [1]Ansibleとは
  • 短期連載
    HashiCorp Vaultではじめるシークレット管理
    [最終回]KubernetesからVaultを利用しよう

著者プロフィール

小飼弾(こがいだん)

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

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

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