Swift 2.2 Released! で Swift 2.2 の新機能が紹介されたので訳してみます。まずは SE-0001: Allow (most) keywords as argument labels から。
原文に従ってこの訳は Apache License 2.0 とします。
(ほぼ全ての)キーワードを引数ラベルとして認める
- 提案: SE-0001
- 著者: Doug Gregor
- ステータス: 受理 Swift 2.2 で実装された (Bug)
はじめに
引数ラベルは Swift の関数のインターフェースの重要な部分です。ある引数が関数に何をするものかを記述し、可読性を向上させます。時として、ある引数にとってもっとも自然なラベルが in
, repeat
, defer
のような言語キーワードと被ってしまうことがあります。そのようなキーワードは、よりよい関数インターフェースのために引数ラベルとして許容されるべきです。
動機
関数の引数にとって最も良い引数ラベルが言語キーワードと被ってしまうことがあります。例えば、コレクションのある値のインデックスを見つけるモジュールスコープの関数について考えてみましょう。このラベルの自然な名前は indexOf(_:in:)
でしょう:
indexOf(value, in: collection)
しかし in
はキーワードなので実際には in
をエスケープするためにバッククォートを使わないといけないでしょう:
indexOf(value, `in`: collection)
Swift で新しい API を定義する際、それが理想的な名前ではなくてもキーワードではない別の単語を選ぶ場合が多々あります(この例では within
など)。それでもこの問題は "不要な名前は省略する" というやり方に従った Objective-C の API を使う時にも出てきます。そのような API を使うにはエスケープする必要があります。例えば次の API があります:
event.touchesMatching([.Began, .Moved], `in`: view)
NSXPCInterface(`protocol`: SomeProtocolType.Protocol)
提案手法
inout
, var
, let
以外の全てのキーワードを引数ラベルとして使うことを認めます。これは文法に 3 点影響があります。
上の例で挙げたような呼び出し式。この点について、文法上の曖昧さはありません。"<keyword> :" はこの他の括弧で囲まれた式リスト中の文法生成には現れないからです。これは最も重要な点です。
関数/添字付け/イニシャライザの宣言: この点に関し、上で挙げた 3 つの例外を除くと曖昧さはありません。キーワードには常に識別子、‘:’、‘_’ のいずれかが続くからです。例えば:
func touchesMatching(phase: NSTouchPhase, in view: NSView?) -> Set<NSTouch>
パラメータの前に付いたり修飾したりするキーワード --今のところは "inout" と "let" と "var"-- は元々の意味を引き継ぐ必要があります。もしそのようなキーワードを使う API を発明したとしても、依然としてバッククォートで囲われている必要があるでしょう。
func addParameter(name: String, `inout`: Bool)
- 関数の型: 実際には 2 番目の項目より簡単です。パラメータの名前には常に ‘:’ が続くからです:
(NSTouchPhase, in: NSView?) -> Set<NSTouch>
(String, inout: Bool) -> Void
既存のコードに対する影響
この機能は厳密に追加的なものであり、既存のコードを破壊しません: 幾つかのこれまで文法的に正しくなかったコードを正しいものとするだけで、正しかったコードの振る舞いは変更しません。
考えられる代替案
ここで考えられる一つ目の代替案は何もしないというものです: Swift の API は引数ラベルにキーワードを使うことを避け続けるでしょう。それが最も自然な単語だったとしてもです。(訳注: Objective-C から)取り込まれた API はバッククォートを使い続けるか、名前を変更する必要があるでしょう。この代替案では非常に多くの取り込まれた API (200近く)がある程度 API 名の変更をするか呼び出し側がバッククォートをつけるかし続けないといけません。
二つ目の代替案は in
自体に注目するものです。in
は取り込まれた API で最も一般的な、キーワードになっている引数です。取り込まれた API をざっと調べたところ、in
が既存のキーワードとの競合の 90% を占めていました。さらに in
というキーワードは Swift の文法の 2 箇所だけ--for ループとクロージャ--でしか使われていません。そのためコンテキスト依存にすることができました。しかし、この解決方法はもう少し複雑(もっと多くのコンテキスト依存のキーワードのパースが必要になる)で、一般性に欠けます。