1
/
5

小ネタ Goの識別子とUnicode #golang

先日 The Go Programming Language Specification を読んでいたところ、ふと識別子の章で気になる記述を見つけました。

https://golang.org/ref/spec#Identifiers

identifier = letter { letter | unicode_digit } .

a
_x9
ThisVariableIsExported
αβ

お、そういえば Go では識別子に英数字以外の文字も使えるのでしたね。
よく見てみると仕様書の中でも特殊な変数名が定義されていたりします。

https://golang.org/ref/spec#Constant_expressions

const Σ = 1 - 0.707i // (untyped complex constant)
const Δ = Σ + 2.0e-4 // (untyped complex constant)

さて、この識別子では letter と unicode_digit が使えるそうですが、具体的にどの文字が使えるのでしょうか?
もう少し見てみましょう。

https://golang.org/ref/spec#Source_code_representation

letter = unicode_letter | "_" .
unicode_letter = /* a Unicode code point classified as "Letter" */ .
unicode_digit = /* a Unicode code point classified as "Number, decimal digit" */ .
In The Unicode Standard 8.0, Section 4.5 "General Category" defines a set of character categories. Go treats all characters in any of the Letter categories Lu, Ll, Lt, Lm, or Lo as Unicode letters, and those in the Number category Nd as Unicode digits.

どうやら Unicode にはカテゴリが存在し、Go ではこの L 系または Nd カテゴリに存在する文字と _ ( Pc カテゴリ ) が識別子に使える文字として定義されているようです。

特定の文字がどのカテゴリに属するかどうかは、python の unicodedata モジュールを使うと簡単に知ることができます。

>>> import unicodedata
>>> unicodedata.category('_')
'Pc'

そういえば識別子と言えば、Go では先頭文字が大文字の場合は Exported になるという仕様がありましたね。
以上を踏まえてもう一度見てみましょう。

https://golang.org/ref/spec#Exported_identifiers
An identifier may be exported to permit access to it from another package. An identifier is exported if both:
1. the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
2. the identifier is declared in the package block or it is a field name or method name.
All other identifiers are not exported.

なるほど。
「package blockの中で宣言 または フィールド名かメソッド名」かつ「先頭文字がLuに属する」識別子の場合、Exported になるんですね。

さて、ここで問題です!
とあるパッケージの中で宣言された次の4つの変数のうち、識別子として成り立ち(ちゃんとコンパイルが通る)、かつ Exported なものはどれでしょう?

  1. 11壱一
  2. ʕʘϖʘʔ
  3. Ⲻ_ー
  4. Nj

....

...

..

.

正解は 3. Ⲻ_ー でした!

ちなみに選択肢の文字は全て L 系または N 系のカテゴリに属します。
以下解説。

  1. 「11壱一」 は識別子として成り立ちません。先頭の「1」は Nd カテゴリに属しており、識別子の先頭には unicode_digit が使えないからです。https://play.golang.org/p/FLzZdHAMJW6
  2. 「ʕʘϖʘʔ」は識別子としては成り立ちますが、「ʕ」が Lu カテゴリではないので Unexported です。
  3. 「Ⲻ_ー」は「Ⲻ」が見事に Lu カテゴリなので Exported です。へーー。
  4. 「Nj」は「Nj」が Lt カテゴリなので Unexported です。これで一文字なんですね...。

馴染みのない文字を識別子に使われると混乱しますね。
以上、Unicode の話でした。

Wantedly, Inc.では一緒に働く仲間を募集しています
10 いいね!
10 いいね!
同じタグの記事
今週のランキング
Wantedly, Inc.からお誘い
この話題に共感したら、メンバーと話してみませんか?