なんかこう、GitHub リポジトリのwatchとかしてると、 だいたいアメリカのホリデーシーズンに合わせて自分まで「もう休み」な気分になってしまい。 要するに、12月20日前後にはもう休み気分で。 代わりに1月は2日から仕事に復帰してる感じの人が多く、休みあけた気分に。

Regex パーサー

事の発端は、「C# に Regex リテラルを入れてくれ」とかいう、まあ、芽がない提案なんですが。 issue 自体はだいぶ前からあるものなんですが、ホリデー前後あたりからなぜか再燃。

「芽がない」ってのは、この手の「C# に別言語を埋め込みたい」系の提案が通った試しがないからでして。 今回も、まあ、C# チームの中の人の1人が、

などなど言語機能としては完全否定。

代わりに、IDE機能としては割かし乗り気だったわけですけども、 「休み中の飛行機の中で暇だったから作った」的なノリで、 Regex パーサーを書いちゃったみたいです。

持っている機能は以下のようなもの。

  • VirtualCharService: "\\1@"\1""\\\u0031" みたいな同じ文字列の別表現みたいなのの差を吸収する層
  • new Regex("") の中身に対して働く正規表現パーサー
  • 正規表現が間違っていたら編集時にエラーを検出する
  • 正規表現の構文を見て色付け

まあ、現状、1開発者が休暇中に個人的に作ってみたって感じなので、今後どうなるかはわかりませんが。

あと、「正規表現が間違っていたらエラーに」の方はMicrosoft.CodeAnalysisだからいいとして、 「構文色付け」の方はMicrosoft.VisualStudio.LanguageServicesなんですよね… Visual Studio Code とか for Mac で動くのか…

raw string リテラル

ということで、結局、特別な言語機能なしで Analyzer を書く感じに収まりそうなんですが。 Regex だけの特別扱いというのは今後も芽はないとして。 とはいえ、汎用な機能として C# に追加したい課題はいくつかあったりはします。

1つは、"raw" string リテラル@付きのやつ(逐語的文字列リテラル)よりもさらに、「そのまんま」な文字列リテラルが欲しいという話。 文字列中に \ が頻出することは Regex に限らず結構ありますし。 @"" でも、文字列中の" がやっぱり@"""abc"""みたいな感じでかなり嫌ですし。

てことで、C++ 11 の raw stringみたいに、開始・終了のパターンを任意に変えれるようにしたいという話に(これも前々からある提案の再燃)。

コンパイル時処理

.NET の Regex クラスには、正規表現を解析して、内部的に IL コード生成してキャッシュしておくような機能もありまして。 動的コンパイル。 初回はやたらと遅いものの、何度も同じパターンを調べる場合は圧倒的に速くなります。

でもその、動的にやっちゃうがゆえに初回やたら遅いとか、 AOT を見越して動的コンパイルが使えない環境で困るとか、 結構悩ましいものがあります。

てことで、C# コンパイルの途中の処理をフックしてIL生成できるプラグイン機構を追加してほしいなんて話も度々出たりはするんですが。 Regex の中身のコード生成とかかなり複雑そうで、そういう機構があっても結構きつそう…

C# 7.2 fixes

おまけ。

Visual Studio 2017 15.5をリリースして割とすぐにホリデーシーズンに入ってしまい、C# 関連も一気に動きが鈍くなったわけですが。 一応、15.6に関する計画的なドキュメントはちょこっと更新されていたり。

Language Feature Statusに、 「C# 7.2 fixes」ってセクションが増えています。 おそらくこれが 15.6 でのリリースになります。 今出ている 15.6 のプレビュー版には入っていませんが、次のプレビュー辺りからちらほら入り始めるはず。

まあ、名前通り、基本的にはバグ修正です。 先月書いたやべーやつも直るはずです。 で、ちょこっと文法にも追加?が入ります。

前者は、参照渡しの拡張メソッドrefthisの順序とか、 ref構造体refpartialの順序とか、 15.5 の時点では ref thisref partial の順でないといけなかったのを、どういう語順でもよくするという話。

後者は、通常の引数とin引数でオーバーロードを作ってしまった場合(例えば、void M(T x)void M(in T x))、M(T x) の方を呼び出す手段がなかったという問題の解消です。M(value) と呼べば M(T x) を、M(in value) と呼べば M(in T x) を呼ぶようになります。

いずれも、まあ既存コードは壊しませんし、今までできなかったことができるようになるだけなので、 「バグ修正みたいな物」として扱うみたいです。 要するに、 「ref this の語順でないとコンパイル エラーになる 15.5 の頃の挙動をあえて選びたい」みたいなことは 15.6 以降ではできなると思われます。