Swift Digest
SE-0144 | Swift Evolution

Allow Single Dollar Sign as a Valid Identifier

Proposal
SE-0144
Authors
Ankur Patel
Review Manager
Chris Lattner
Status
Rejected

01 何が問題だったのか

Swift 3.0 までは、$ 一文字だけを識別子として利用することができました。たとえば次のようなコードが通っていました。

let $ = 10

let $: (Int) -> Int = { $0 * $0 }

class $ {}

この書き方は Dollar のようなライブラリが $ を名前空間として使う際に利用されていました。

しかし Swift コンパイラは途中の変更で $ 単体を識別子として受け付けなくなり、上記のコードはコンパイルエラーになるようになりました。これは Swift 3.0 互換のコードが Swift 4 以降で動かなくなることを意味します。$ を引き続き使いたい場合は、バッククォートで囲って `$` と書く必要があります。

この変更の背景には次のような考えがあります。

  • $ は元々識別子として意図されたものではなく、The Swift Programming Language にも識別子として記載されていなかった。
  • $ は見た目としては識別子というより演算子や記号の性格が強い。
  • $ から始まる名前は、匿名クロージャ引数($0$1 など)やデバッガ/REPL の一時変数($R0 など)として既に使われている名前空間である。数字や文字が続く形は従来からきちんと弾かれており、たまたま単独の $ だけが通っていたに過ぎない。

この Proposal は、$ を単独で識別子として使えるようにコンパイラの挙動を元に戻すことを提案したものです。

02 どのように解決されるのか

この Proposal は Rejected(却下) されました。したがって、$ 単独での識別子利用は Swift 4 以降でも復活せず、従来どおりコンパイルエラーのままです。

let $ = 10                           // error
let $: (Int) -> Int = { $0 * $0 }    // error
class $ {}                           // error

$ を識別子として使いたい場合は、バッククォートで囲う必要があります。

let `$` = 10

let `$`: (Int) -> Int = { $0 * $0 }

class `$` {}

Swift 4 のマイグレーションツールでは、$ 単独の識別子に対して `$` への置き換えを促すヒントが出力されるようになっています。Dollar のような $ を名前空間として使うライブラリは、この変更に追随してバッククォート付きの表記に移行するか、別の名前空間を採用する必要があります。

却下の背景は元 Proposal の「Motivation」で挙げられているとおり、$ は本来識別子ではなく記号・演算子に近い文字であり、クロージャの暗黙引数やデバッガ/REPL の一時変数といった特別な用途のための接頭辞として位置付けられていることが重視されました。単独の $ だけが識別子として通っていたのは過去の言語仕様の穴であり、Swift 4 での修正によってその穴を塞いだ、という整理です。