JavaScriptの識別子に中黒が使えるようになった2024年06月07日 10時21分

JavaScriptの識別子(変数名、関数名、プロパティ名など)の2文字目以降に中黒「・」(U+30FB KATAKANA MIDDLE DOT)が使えるようになりました。以下のコードはChrome 124では構文エラーになりますが、Chrome 125では問題なく実行できます。

const シン・ゴジラ = 2016;

JavaScriptの識別子

中黒が使えるようになったのは、JavaScript(ECMAScript)の仕様が変わったからではありません。変わったのはUnicodeの仕様のほうです。Unicode 15.1.0(2023年9月)においてOther_ID_Continueプロパティ(を持つ文字の集まり)に中黒が追加されました。

そもそもJavaScriptの識別子に使える文字は、Unicodeを参照して定義されています。ECMAScript 2023(2023年6月)では以下のようになっています。

識別子の1文字目に使える文字
  • UnicodeのID_Startプロパティを持つ文字
  • $(U+0024 DOLLAR SIGN)
  • _(U+005F LOW LINE)
識別子の2文字目以降に使える文字
  • UnicodeのID_Continueプロパティを持つ文字
  • $(U+0024 DOLLAR SIGN)
  • ゼロ幅非接合子(U+200C ZERO WIDTH NON-JOINER)
  • ゼロ幅接合子(U+200D ZERO WIDTH JOINER)

(いわゆるアンダースコア「_」はID_Continueプロパティを持つため、2文字目以降にも使えます。)

Unicodeの仕様も毎年のように改定されますが、ECMAScript仕様ではUnicodeの「最新バージョン」が参照されています。

Unicodeの識別子

UnicodeのID_StartID_Continueプロパティは、各種の「識別子」に使える文字として推奨されるものを表しており、UAX #31 Unicode Identifiers and Syntaxで以下の文字を含むものとして定義されています。

ID_Startプロパティ
  • 一般カテゴリがLetterである文字
  • 一般カテゴリがLetter_Numberである文字
  • Other_ID_Startプロパティを持つ文字
  • ただしPattern_SyntaxプロパティまたはPattern_White_Spaceプロパティを持つ文字を除く(具体的には(U+2E2F VERTICAL TILDE)が除かれる)
ID_Continueプロパティ
  • ID_Startプロパティを持つ文字
  • 一般カテゴリがNonspacing_Markである文字
  • 一般カテゴリがSpacing_Markである文字
  • 一般カテゴリがDecimal_Numberである文字
  • 一般カテゴリがConnector_Punctuationである文字
  • Other_ID_Continueプロパティを持つ文字
  • ただしPattern_SyntaxプロパティまたはPattern_White_Spaceプロパティを持つ文字を除く

ここでOther_ID_StartプロパティとOther_ID_Continueプロパティというのは、後方互換性のためにそれぞれID_StartプロパティとID_Continueプロパティに含めるべき文字を表しています。Other_ID_Continueプロパティに中黒(U+30FB)が追加されたことで、巡り巡ってJavaScriptの識別子に中黒が使えるようになったのです。

なお、中黒だけでなくゼロ幅非接合子(U+200C)とゼロ幅接合子(U+200D)も追加されたため、ECMAScript 2024以降では識別子の2文字目以降に使える文字の定義が「UnicodeのID_Continueプロパティを持つ文字または$(U+0024 DOLLAR SIGN)」と簡潔になる予定です。

過去にも識別子に中黒が使えた

ID_Continueプロパティの後方互換性のために中黒が追加されたということは、さらに以前は中黒がID_Continueプロパティに含まれていたのでしょうか?

まさにその通りで、Unicode 4.0.1(2004年5月)以前は中黒の一般カテゴリがConnector_Punctuationになっており、結果としてID_Continueプロパティに含まれていました。Unicode 4.1.0(2005年3月)で中黒の一般カテゴリがOther_Punctuationに変更され、ID_Continueプロパティに含まれなくなっていたのです。

ECMAScript 5.1ではUnicode 3.0以上への適合が求められていたため、ECMAScript 3(1999年12月)~5.1(2011年6月)の間は中黒を識別子に使えた可能性があります。(ECMAScript 2(1998年8月)以前はASCIIの範囲内の文字のみ識別子に使用可能、ECMAScript 2015(ES6、2015年6月)以降はUnicode 5.1.0以上への適合が求められる。)

他のプログラミング言語の識別子

識別子の定義にUAX #31を参照しているのはJavaScriptだけではありません。CC++PerlPythonRustなど多くのプログラミング言語がUAX #31を参照しています。これらの言語でもそのうち識別子に中黒が使えるようになるでしょう(\p{Word}との共通部分を採用しているPerlを除く)。

なお、JavaScript以外ではID_StartID_Continueプロパティではなく、XID_StartXID_Continueプロパティを参照していることが多いです。これらのプロパティは、ある識別子にUnicode正規化を適用しても識別子として有効であり続けることを保証するため、それぞれID_StartID_Continueプロパティからいくつかの文字を除外しています。

参考文献

Windowsでプロキシ自動設定ファイルを適用するPowerShellスクリプト2020年03月21日 22時23分

Windowsで一時的にプロキシ自動設定ファイル(プロキシ自動構成スクリプト、pacファイル)を利用したいとき、

  • プロキシ自動設定ファイルを配信するHTTPサーバーを立てなければいけない。(以前はローカルファイルが使えたが、Windows 10 Creators Updateから使えなくなった。)
  • Windowsの「プロキシ」設定画面で「スクリプトのアドレス」を指定しなければいけない。

という手間があります。

そこで、プロキシ自動設定ファイルを配信するHTTPサーバーを立ち上げ、そのURLをWindowsのプロキシ設定に指定するPowerShellスクリプトを書きました。

上記リンク先のスクリプトをローカルに保存し、Explorerでスクリプトファイルのコンテキストメニューから「PowerShell で実行」を選択すると、コンソールウィンドウが開き、スクリプト中に記述されたプロキシ自動設定が適用された状態になります。コンソールウィンドウ内でCtrl + Cを押下すれば、プロキシ自動設定が解除されます。

なお、プロキシ自動設定でSOCKSプロキシを使う場合、そのためのSSH接続は別途立ち上げておく必要があります。

既知の不具合

EdgeやInternet Explorerではプロキシ自動設定が期待通り適用されないことがあるようです。

プロキシ設定の変更をブラウザに通知する

プロキシ設定はレジストリに保存されていますが、レジストリの値を書き換えるだけではうまく機能しませんでした。どうもプロキシ設定が変更されたことをWebブラウザなどの各アプリケーションに伝えるために、Windows APIを呼び出す必要があるようです(スクリプト中のRefresh-Proxy-Settings関数の処理)。

もっと言うと、プロキシ設定の変更自体もレジストリを直接いじるのではなく、WinInetライブラリのInternetSetOption関数経由でやったほうがよいようです。ただし、そのためには構造体を定義するなど、PowerShellスクリプト中にC#のコードを書く必要があり、面倒になってやっていません。

Windows PowerShellの感想

今回初めてWindows PowerShellを書いたのですが、.NET Frameworkをそのまま使え、C#のコードを書け、Windows APIまで呼び出せるなど、何でもできる感じで感心しました。Taskオブジェクトを直接扱うことでC#のasync/await相当の処理を実現できるのも面白かったです。

もっとも、気をつけないと「PowerShellを書いていたつもりが、いつの間にかC#を書いていた」ということになりかねませんが(笑)

xargsで入力が空のときに何も実行しない2019年12月31日 19時56分

xargsコマンドで入力が空のときは何も実行しないようにしたいのですが、BSD版(macOSなど)とGNU版(Linuxなど)などで挙動が異なります。BSD版は最初からそのような挙動なのに対し、GNU版では--no-run-if-emptyオプションをつけないとそのような挙動になりません。両者で挙動を合わせるために、シェルスクリプトで以下のように書けます。

NO_RUN_IF_EMPTY=$(: | xargs echo '--no-run-if-empty')
command1 | xargs $NO_RUN_IF_EMPTY command2

コロン(:)は何もしないコマンドであり、パイプでつながれたxargsの入力も空となります。なので、BSD版ではechoコマンドが実行されずNO_RUN_IF_EMPTY変数の値が空文字列となり、一方GNU版ではechoコマンドが実行されNO_RUN_IF_EMPTY変数の値に文字列'--no-run-if-empty'が入ります。

参考: GNU版, BSD版 xargsの挙動の違い - syohex’s diary

Windows 10 で Emacs キーバインディングを利用するための設定のメモ2016年01月31日 11時26分

Windows の操作全般および MS-IME で Emacs のようなキーバインディングを利用するための個人的なメモ。

Ctrl キーの位置調整

Change Key を利用。管理者として実行する。

  • CapsLock → Ctrl (左)
  • カタカナ/ひらがな → Shift (右)
  • 半角/全角 → Esc

XKeymacs の設定

XKeymacs のスナップショットバージョンを利用。Explorer を「管理者として実行」し、その上で C:\Program Files にフォルダをコピー。

dot.xkeymacs

以下の内容でファイル %APPDATA%\dot.xkeymacs (たいていは C:\Users\{user}\AppData\Roaming\dot.xkeymacs) を作成。

(fset 'browser-back [browser-back])
(fset 'browser-forward [browser-forward])
(fset 'find-next [f3])
(fset 'find-previous [?\S-f3])

プロパティ全般

  • 「ダイアログにはダイアログ専用の設定を利用する」を無効化
    • 個人的には設定を共通化したほうが楽。
  • 「Microsoft IME (IME)」に対しては「XKeymacs を無効にする」を選択
    • MS-IME には後述の設定を適用するので、XKeymacs 側で何かする必要はない。

(2021-04-25 追記)

プロパティの「基本」タブ

  • 「アクティブウィンドウから離れる」の C-z 及び M-F12 を無効化
    • C-z は素通しさせ、「元に戻す」として扱う。
  • 「消去、編集」の C-t 及び C-x C-t を無効化
    • C-t は screen でのメタキーとしてのみ用い、他の用途には使わない。
  • 「その他」の Esc 及び C-[ を無効化
    • メタキーには Alt のみ用い、Esc は Esc としてのみ用いる。
  • 「IME の切替え」の全項目を無効化
    • IME のオン / オフは変換 / 無変換キーで行う。
  • 「その他」の C-x h を無効化
  • 「移動」の C-l、「消去、編集」の C-k、「その他」の C-u を無効化
    • MS-IME に対して「XKeymacs を無効にする」としていても、Firefox など (IME で入力中の文字列を自前で描画するアプリケーション?) では MS-IME での入力中に XKeymacs の設定が適用されてしまうので、MS-IME のキー設定と干渉するものは無効化しておく。
  • 「その他」の C-0 ... C-9 を無効化
    • 誤爆しかしない。必要なコマンドの数を事前に算出し、正しい数値のキーを打つのは私には困難。

プロパティの「詳細」タブ

  • 「その他」の Esc に Ctrl + [ を割り当て
    • C-[ は Meta ではなく単なる Esc として用いる。
  • 「その他」の Temporarily Disable XKeymacs に Ctrl + ; を割り当て
    • C-; C-○ と打つことでネイティブのショートカットキーを利用できる。";" (セミコロン) はホームポジションなので打つのも簡単。
  • 「その他」の Select All に Ctrl + X H を割り当て
    • Firefox Nightly で C-x h が期待通り動作しないので、これをネイティブの「すべて選択」に置換する
  • 「その他」の newline に Ctrl + J を割り当て
  • 「オリジナルコマンド」の browser-back に Meta + , を、browser-forward に Meta + . を、find-next に Ctrl + . を、find-previous に Ctrl + , をそれぞれ割り当て
    • "," (カンマ) は "<" (小なり) すなわち「←」(戻る方向) を、"." (ピリオド) は ">" (大なり) すなわち「→」(進む方向) を、それぞれ表す。

オプション

  • 「XKeymacs」の「ログオン時に実行」を有効化
  • 「コマンド プロンプト」の「ファイル名自動補完」を無効化
    • 個人的には使わない。

(2021-04-25 追記)

MS-IME の設定

  • 「スペースの入力」を「常に半角」
  • 「Shift キー単独で英数モードに切り替える」を有効化
  • 英数字及び記号類を「常に半角に変換」、ただし「~」のみ「変換しない」
    • 「英字」「数字」のみ「常に半角に変換」とし、「記号」は「前回の変換結果に従う」のまま (2021-04-25 追記)

MS-IME のキー設定

インポート / エクスポート機能がなさそうなので、ひとつずつ設定しなおしている。

キー 入力/変換済み文字なし 入力文字のみ 変換済み 候補一覧表示中 文節長変更中 変換済み文節内入力文字 備考
無変換 IME-オフ 全消去 文節戻し 候補閉 文節戻し 全戻し 何もなければ IME オフ、ほかは Esc と同じ
Shift + 無変換 かな切替 かな切替 かな切替 かな切替 かな切替 かな切替
変換 IME-オン 何もなければ IME オン、ほかは変更なし
Ctrl + 変換 再変換 何もなければ再変換、ほかは変更なし
Ctrl + A 文字先頭 文節先頭 候補先頭 - 文字先頭 Home と大体同じ
Ctrl + B 文字左 文節左or文字左 文節左or文字左 文節左 文字左 「←」と同じ
Ctrl + C - - - - - 握りつぶす
Ctrl + D 1文字削除 1文字削除 候補閉 - 1文字削除 Delete と同じ
Ctrl + E 文字末尾 文節末尾 候補最後 - 文字末尾 End と大体同じ
Ctrl + F 文字右 文節右 文節右 文節右 文字右 「→」と同じ
Ctrl + G 全消去 文節戻し 候補閉 文節戻し 全戻し Esc と同じ
Ctrl + I 予測候補表示 - 候補表示切替 - - Tab と同じ
Ctrl + J 全確定 全確定 候補選択+確定 全確定 全確定 Enter と同じ
Ctrl + N 全変換 変換+次 変換+次 文節変換 全変換
Ctrl + P 全変換 前候補 前候補 文節変換 全変換
Ctrl + Q - - - - - 握りつぶす
Ctrl + R - - - - - 握りつぶす
Ctrl + S - - - - - 握りつぶす
Ctrl + U カタカナ カタカナ カタカナ カタカナ カタカナ
Ctrl + V - - - - - 握りつぶす
Ctrl + W - - - - - 握りつぶす
Ctrl + X - - - - - 握りつぶす
Ctrl + [ 全消去 文節戻し 候補閉 文節戻し 全戻し Esc と同じ (2021-04-25 追記)

Ctrl + H/K/L/M/O/T/Y/Z は変更なし。

MS-IME のキー設定の「機能選択」には「-」という項目がふたつ存在するが、先頭のものは MS-IME を利用しているアプリケーション側にそのキーを伝え、末尾のものは MS-IME 内でそのキーを握りつぶす。

あるキーに対する項目を選択した状態で「キー追加」を実行すると、元の項目をコピーして新たな項目を追加できる。(2021-04-25 追記)

XKeymacs を起動していると「割り当てるキー」を入力できないことがあるので、XKeymacs を終了した状態で設定する。(2021-04-25 追記)

はてなでコードを書くときに気をつけていること2011年12月18日 14時37分

こんにちは、はてなでアプリケーションエンジニアをしている nanto_vi です。この記事は Hatena::Staff Advent Calendar 2011 の一環として書いています。Advent Calendar の会場ははてなブログとなっていますが、主催の antipop さんに尋ねたところ何でもよいというような返答があったのでここで書きます。

はじめに謝っておきますが、この記事ははてなとほとんど関係がありません。タイトルに「はてな」と入っているのは Advent Calendar の要件を満たすための目くらましあり、内容はといえばはてなのノウハウでもなんでもない、私が最近個人的に心がけていることです。ごめんなさい。

できれば明示的に

業務で書くコードは複数人により読み書きされメンテナンスされるので、わかりやすさが重要になってきます。わかりやすさを保つためには暗黙的に行われる操作を減らし、明示的にコードに表した方がよいと感じます。たとえば、Perl では、

use Encode;

# encode_utf8 関数は Encode モジュールで定義されている
my $octets = encode_utf8 $string;

のようにモジュール読み込み時に自動的に関数をインポートすることができますが、それよりも、

use Encode qw/encode_utf8/;

my $octets = encode_utf8 $string;

のようにインポートする関数を明示的に指定したほうが、その関数がどこで定義されているのかわかりやすいでしょう。

個人的には、関数や変数の名前で grep をかけてその定義(外部で定義されている場合は宣言)を探し出せることが、「明示的」であるための最低線ではないかと思います。

入力には正規化を、出力には符号化を

アプリケーションを作るうえで入出力の扱いは避けて通れません。入力元はユーザーだったりバッチ処理スクリプトの引数だったり、出力先はユーザーだったりデータベースサーバーだったりしますが、いずれにおいても入力には正規化処理を、出力には符号化処理を、それぞれ施すことになります。

正規化は一般に不可逆です。空白文字類をすべてスペースに置換した後はもともとスペース以外の空白文字が含まれていたのかわかりませんし、数値「42」を生み出した入力は "42" でも "42.0" でも、はたまた "0x2A" でもありえます。

符号化は一般に可逆です。あるデータをユーザーのもとへ送り届けるのに、そのデータを HTML のテキストとして扱えるよう一部文字を文字参照の形に符号化し、その HTML ソース全体を文字符号化方式 UTF-8 をもって符号化し、さらには HTTP メッセージに、TCP のセッションに、IP のパケットにと符号化を重ねていきますが、それらすべては符号化規則を逆に適用することで元の形式へ復元できます。

たとえば HTML として解析され、その結果が JavaScript の文字列として、HTML として、URI としてと順に解析されるデータを Template-Toolkit で出力する場合、解析の逆順でそれぞの形式に応じた符号化を施す必要があります。

<script type="text/javascript">
document.write('<a href="/search?q=[% word | uri | html | js %]">検索<\/a>');
</script>

script 要素の内容は CDATA 型であり文字参照は解決されないので、最後に html フィルタをかけることはしません。また、そもそもこのような多重にフィルタをかける事態は避けたほうが賢明でしょう。

入出力いずれにおいても、データがどういう形式で扱われるのかを意識し、それに応じた正規化処理または符号化処理を施すことで、意図しない入力が致命的な挙動を引き起こすこともある程度は防げるのではないかと考えます。

次は hitode909 さんです。