Archive for 1月 2015
C# Design Notes 1/28版
次のが来てた。
https://github.com/dotnet/roslyn/issues/180
21日のNotesが公開遅かっただけで、ミーティング自体は1週間経ってますもんね。
今回は、
- Immutable types
- Safe Fixed-Size buffers
- Pattern matching
- Records
の話。前の2つはすでに個別の issue ページあり。
後ろ2つは、CodePlex 時代に仕様書のドラフトあり(http://roslyn.codeplex.com/discussions/560339)。
C# 6の草案の中には元々Declaration expressionsとPrimary constructorsっていう便利そうな機能があったのが、最終案ではこの2つが消えています。その理由が、このPattern matchingsとRecordsで、「より大きな機能として発展させる。半端な状態で6に入れてしまうわけにもいかない。」という理由で、7を待つことになったものです。
C# Design Notes / テーマ
一昨日(C# Design Notes / デザイン プロセスについて)に引き続いて。C# 7がらみの話の続き。 一昨日はどういうプロセスでC#の仕様が決まっていくかという部分について説明(というか、全文和訳)しました。 今日は、C# 7(に向けた、6リリース後)のC#のテーマについて。C# Design Meeting Notes の 2. のところに書かれている内容の概要になります。
背景
C# 7どころか、C# 6もまだリリース前なわけですが。昨年末にC# 6の仕様はfixしてリリース準備に入ったとはいえ、7はだいぶ先の話です。これまでの周期から考えると1・2年先になるのかなぁ。
つまり、だいぶ早い時期からオープンなディスカッションをしようとしている。今ならアイディア出し放題、C#チームの出してくる案にもコメント付け放題。(こういう場、特に英語ですし、苦手な方でも、いずれ、UserVoice等での投票があるはずなので、その際だけでも是非。) こういう好き放題できる状況で、アイディアが散逸してしまわないよう、C# 7のテーマが提示されています。
もちろん、「それ以外は絶対にやらない」というものではないんですが、同じ方向に向かって進んでいけるよう長期的なゴールを設定しています。
テーマ
そのテーマですが、今、大まかに提示されているのは以下のようなもの。
- Working with data
- Performance and reliability (and interop)
- Componentization
- Distribution
- Metaprogramming
- Null
Working with data
OOPの「振る舞い中心」(behavior-centric)なモデリング手法も多くのよいことがあるけども、関数型な「データ中心」(data-centric) な手法も(C# 3.0の頃からやってはいますが)推し進めていきたいという内容。
このテーマの元、さらに細かく分けていくと、以下のようなことを考えているそうです。
- pattern matching
- tuples
- “denotable” anonymous types
- “records” – compact ways of describing shapes
- working with common data structures (List/Dictionary)
- extension members
- slicing
- immutability
- structural typing/shapes?
Performance and reliability (and interop)
(Javaと違って)値型とか具体化した(reified)ジェネリックとか、実行性能面に関する考慮はあるものの、まだまだ性能を伸ばす余地がある。
一方で、(C++と違って)メモリ管理が安全ではあるものの、決定論的挙動がしにくかったり、信頼性に関する余地もまだある。
ということで、その余地を埋めるように、より性能面・信頼性を求めていきたいとのこと。
Componentization
「 言語の」というか.NETのランタイムやVSなどのツール寄りの話ですが、コンポーネント化も重要な課題です。要は、一枚岩なでかいシステムだと世の中の急速な進歩について行きづらいので、どうにかしてモジュラーな機能提供ができるよう、要因を分解して組み合わせて(factored and combined) プログラムを作れるようにしていくというのが重要な課題です。
このテーマの元には以下のような機能が考えられています。
- generating reference assemblies
- static linking instead of IL merge
- determinism
- NuGet support
- versioning and adaptive light-up
Distribution
ここでいうDistributionは、いわゆる分散コンピューティングのことです。C# 5で async/await が入りましたが、まだいくつか取り組まないと行けない課題は残っています。
- async/await は単一の値を非同期に受け取るのには非常に強力な機能ですが、シーケンス データを受け取るのには適していません。
- シリアル化に関しても、immutable なデータへの対応や、コストの高いリフレクションを必要としないようなものを、カスタマイズ可能な形で提供することが求められている
Metaprogramming
Roslynが出立ての頃からずっと期待をかけられていることの際たるものはメタプログラミングでしょう。Roslyn(というライブラリ)自体はそれを狙って作られたものですが、C#という言語レベルではメタプログラミングをうまく取り扱えるような機能がまだまだ不足しています。
RoslynはVisual Studioの裏で、リアルタイムに常時動いていて、キータイプしたそばからコードを解析して警告を出したり、訂正機能を提供したりします。これを活用してメタプログラミングができるのなら、(よくあるビルド時コード生成や、リフレクションでの動的なメタプログラミングと違って)リアルタイムにコード生成して、生成結果の解析・警告・訂正ができるようになるはずです。
ですが、まあ、コード生成にはいろいろな面倒事があります。そういう面倒を減らせるような機能が求められます。例えば以下のようなものが挙がっています。
- Virtual extension methods/default interface implementations
- Improvements to generic constraints, e.g.: ◦generic constructor constraints
- delegate and enum constraints
- operators or object shapes as constraints (or interfaces), e.g. similar to C++ concepts
- mixins or traits
- delegation
Null
「非null型を早く!」といわれ続けて久しいわけですが。ただ、昔からさんざん、その難しさも言われています(参考: Eric Lippertによる解説)。
それでも、もっと野心少ない妥協的なアプローチでもいいので、非null型は必要な機能でしょう。
その他
これらのテーマにかからないようなものもいくつか挙げられています。
- Type Provider
- Better better betterness
- Scripting
- params IEnumerable
- Binary literals and digit separators
最後に
というようなものが、C# 7が向かおうとしている方向性です。
それぞれの詳細についてはおいおいこのブログで、1つずつ書いていくかも。一気に情報出されるとほんと大変。
ちなみに、このDesign Notes自体はCloseされました。この Issue 中で出た意見は今後のデザイン ミーティングに反映されていくでしょう。そして、機能ごとに「提案」 Issue ができていくことになります。 とりあえず、今すでにある(要するに、今回のDesign Notes中ですでに書かれているような)「提案」の Issue ページができました:
- Proposal: ‘readonly’ for Locals and Parameters #115
- Proposal: Lambda Capture Lists #117
- Proposal: Ref Returns and Locals #118
- Proposal: Method Contracts #119
- Proposal: Slicing #120
- Proposal: Fixed-size buffers enhancements #126
- Proposal: [DoesNotReturn] #127
- Proposal: Immutable Types #159
- Proposal: move #160
- Proposal: Destructible Types #161
- Proposal: Static Linking #162
あと、C# のデザイン ミーティングとは別に、Interactive (要するにREPLとかスクリプティング)のミーティングのデザイン ノートも公開されたみたいです。
C# Design Notes / デザイン プロセスについて
Roslynプロジェクトで、GitHubへの移行後初の「C# Design Notes」が公開されたみたいです。
https://github.com/dotnet/roslyn/issues/98
「続に言うC# 7」(順調に行けばC# 7になるであろうもの)に関する話題も初お目見え。単に「こんな仕様を考えています」という話出はなくて、仕様決定プロセス自体をもっとオープンにしていく話や、どういうテーマを持って決めていこうとしているのかという話が含まれています。
今出ている「新機能候補」については、どうせ変わるだろうし、さらっと流す感じで。ここでは、どちらかというと、デザイン プロセスとかテーマの話を中心に軽く和訳しておこうかと。
とりあえず、デザイン プロセスに関する話を書いてたら、気が付いたら全訳してた。今日はここまで(C# 7 で取り組むテーマや、具体的な機能案の話は後日)。
以下、その翻訳内容。
デザイン プロセス
昨年の「C# 6 設計」に関する design notes を、CodePlex 上で公に共有することは大いに成功した。我々がどう考えているかを、コミュニティがリアルタイムに見て、応えることができることは、大変高く評価された。
今回、さらにオープン性を増すことを望む。
- デザインのサイクルの初期からコミュニティを巻き込みたい。(この notes のように!)
- デザイン ノート (現在では GitHub の issue を利用)に加えて、機能の提案書についても、その機能の現在のデザインを反映するよう保守していく(例えば、Markdownドキュメントをチェックインするなどして)。
- デザイン ミーティングの録画を公開するか、あるいは、ストリーミング配信することを考えている。
- マイクロソフト外のメンバーもデザイン チームに追加することを考えている。
デザイン チーム
C# 7 デザイン チームの現在の構成は以下の通り
- Anders Hejlsberg
- Mads Torgersen
- Lucian Wischik
- Matt Warren
- Neal Gafter
- Anthony D. Green
- Stephen Toub
- Kevin Pilch-Bisson
- Vance Morrison
- Immo Landwerth
Anders は chief language arghitect で、「いずれ必要になるであろう」(“should that ever become necessary” で、そういう熟語っぽい?たぶん)、最終的な発言権を持つ。Mads は C# の language PM で、議題をまとめ、ミーティングを取り仕切り、このノート を取っている。
始めに、我々は週に4時間ミーティングを行い、全体的なフォーカス領域を決定する。Visual Basic のデザイン ミーティングがこれと別に行われることは、この最初の期間の間はなくて、今回のこの全体的な決定の多くはほぼ、C# と VB の両方に適応され、協力が必要である。
機能のアイディア
誰でも、GitHub 上の issue として、機能に関するアイディアを提案できる。我々はそれに目を通して、言語デザインへのインプットとして使う。
機能に関する興味の度合いを測る方法として、提案は UserVoice (投票システム)上に掲載する。これは重要で、なぜかというと、この GitHub リポジトリに入り浸ってくれるような方々は、必ずしも、我々の開発者母体の代表者ではないからである。
デザイン ノート
デザイン ノートは「その時点における」ドキュメントで、毎度、GitHub 上の issue として上げていく。しばらくの間、みなさんがその issue にコメントでき、そのリアクションは以降のミーティングに反映される。
オーナーと提案
デザイン チームが機能に関するアイディア取り組むと決めた場合、そのアイディアに関するオーナーを選出する(典型的には、オーナーはデザイン チームのメンバーの誰か)。オーナーは、その機能のデザインに関連するアクティビティを推進する(例えば、フィードバックを集め、各種ミーティングを進めるなど)。もっとも重要な点として、オーナーは提案ドキュメント(機能の現状を記述)の保守し、その機能に関する議論があった複数のデザイン ノート間を相互リンクしていくことについての責任を持つ。
提案は時間とともに発展していくであろうものなので、履歴の追跡があるリポジトリ内のドキュメントであるべきである。最初に提案された時や、大きな改正があった時には、おそらく issue として上げて、コメントを集める場とする。提案の pull-request も可能である。
この過程を楽しみ、バランスを取っていきたい。
その他、オープン性を増すために
その他、何かアイディアがあれば非常に興味がある。(ミーティングの)録画公開やストリーミング配信などデザイン ミーティング自体に対する案、マイクロソフト外の指導的な人物(例えば、産業界の重要人物など)をミーティングに迎える、などなど。もちろん、我々が活用したいような洞察を持つ人が誰かいれば、「ゲスト」(物理的でも仮想的でも)参加についてもオープンである。
しかしながら、これはゆっくりと進めていく。始めからすぐにとは考えていない。
決定
非常に重要な気に留めておいてほしい点として、C# デザイン チームはいまだ、この言語を管理している。これは民主的な(democratic)プロセスではない。我々はコメントは UserVoice 投票から計り知れない価値を引きだしはするが、C# の最終的な統治モデルは優しい独裁者(benevolent dictatorship)である。我々の考えでは、小さく緊密に結びついた、長期的に関われるメンバーでのデザインこそ、C#を優雅で、一貫していて、大きすぎず、いわゆる「designed by committee」(船頭多くして船が山に上るようなもの)ではないものに保つ正しいモデルである。
もしデザイン チーム内で合意が得られなかったなら、典型的にはそれは、ミーティング後に個別でより深い洞察ができるであろう徴候である。たいていは、その日のうちの投票や、言語の「全ての父」(Allfather: 主神)に最終決定を委ねる必要はない。
プロトタイプ
理想的には、議論するすべての機能についてプロトタイプ作成して、その機能から良い感触を得、コミュニティからのフィードバックを可能な限り集められるようにすべきである。それは現実的ではないだろうが、よい機能候補がひとたび見つかれば、飛び込んでみるべきだろう。
プロトタイプ作成のコストが核心である。機能によるだろうが、ときには急ぎで使い捨てなプロトタイプがほしくなるし、またあるときは実際の実装の初期バージョンが必要になる。
これは、デザイン チーム、製品チーム、もしくは、コミュニティの誰かによって行われるだろう。
アジェンダ
ミーティングで何が議論できる状態にあるか決めるのは、通常は Mads の債務である。一般に、デザイン チームのメンバーの誰かが何かをアジェンダに載せたい場合、そのことに納得している。ミーティングで計画通りに終わる保証はない。ここで公になっているノートはただ、実際に議論があった内容の概要をアジェンダとして示している。
extern alias
最近暇を見ては、++C++; の各所に、C# 6.0 の話を追記して回っているわけですが。今日は using static のあたりの話を。
そのついでというか、名前空間のページを見返していて、ふと、外部エイリアスのあたりにも追記。
- 外部エイリアス
- https://github.com/ufcpp/UfcppSample/tree/master/StructuredProgramming/ExternAliasConsoleApplication
「こんな機能もあったなぁ」というか、「ないと確かに困ることが原理的にはあり得る」的な、普段あんまり日の目を見ない機能です。
が、最近仕事で使った。追記した例にあるような、バックポート品と正規品の混在のせいなんですけども。
というのも、以下のようなライブラリを作っていまして。
- IteratorTasks: イテレーター(yield return)ベースで、.NET 4 以降の Task クラス(System.Threading.Tasks 名前空間)もどきの機能を提供するライブラリ
要は Unity 用。Unity は非同期処理をイテレーターベースでやるわけですが、非同期処理の戻り値とりたいとか、ContinueWith とか WhenAll, WhenAny したいとか、結局、Task が持っている機能はほぼほしくなるので、じゃあ、標準の Task とシグネチャ(クラス名、メソッド名、引数)合わせようと。あと、非同期処理のためだけに MonoBehaviour に依存するとかちょっと。Unity のクラス設計まずすぎて。
こういう、「最新環境が使えないからしょうがなく、最新の機能の劣化コピーをバックポート」みたいなものは早く滅びたいんですけどもね。最新環境が使えるようになることで、「役割は終えた」とか言って引退したい… というような恨み節を、すでにかれこれ3年くらいは言い続け、その間結構アップデートも掛けてしまっているわけです。ほんと、無駄な作業だ…
で、Taskクラス自体は、awaitではなくてyield returnを使っている時点で完全互換とは行かないので、名前空間を変えています(System.Threading.Tasks じゃなくて IteratorTasks)。が、いくつか、互換性がある(DLL 参照を切り替えるだけで本家とIteratorTasks版を切り替えれる)ものについては、名前空間まで一緒だったり。
そして、テスト コードの類では、普通に .NET 4.5 環境から、その IteratorTasks 依存なコードを呼び出しています。結果、いくつかのクラスで、別クラスなのに名前空間もクラス名もメソッド名も引数も完全に一致した状態。そして、その呼び分けのために使ったのが、外部エイリアス(extern alias)機能。「ああ、extern aliasってこう使うものなんだ」とか思ったので、ついでだから足してみました。
Visual Studio CTP 5 での C# 6.0
http://blogs.msdn.com/b/visualstudio/archive/2015/01/16/visual-studio-2015-cpt-5-now-available.aspx
Visual Studio 2015 が CTP 5 になったそうです。
CTPも5個目かー。細かくプレビュー出すなぁ。早い段階からいろいろ試せるのはありがたい話ですが。
さて、で、CTP 5 で C# コンパイラーも更新されました。
「仕様が変わること決定済みだけど、2014/11プレビューでは変更前のままなんだ」といわれ続けていた機能が、ちゃんと正式仕様どおりの実装に。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using static System.Console; // using → using static | |
class Program | |
{ | |
static void Main() | |
{ | |
var x = int.Parse(ReadLine()); | |
WriteLine($"{nameof(x)} = {x}"); // "\{x}" → $"{x}" | |
} | |
static int Test(int x) => x; | |
} |
- クラスの静的メソッドインポート用の構文が、using (名前空間と一緒) → using static (static を追加)
- string interpolation の構文が “\{x}” (”” の中に \) → $”{x}” (“” の前に $)
- (CTP 5でもまだなさそう)
string interpolation は、IFormattable に代入するときは直接の文字列化じゃなくて、いったん IFormattable を作るように - nameof の中にある程度式を書けるように
using staticは、staticを付けないとどういうことになるかというと…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using My.X; | |
public class Program | |
{ | |
public static void Main() | |
{ | |
var name = nameof(Main); // invocation of the My.X.nameof method | |
Console.WriteLine(name); | |
} | |
} | |
namespace My | |
{ | |
public static class X | |
{ | |
public static string nameof(Action x) => ""; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; // using static class, not namespace (warning only, no error) | |
public class Program | |
{ | |
public static void Main() | |
{ | |
var name = nameof(Main); // invocation of the nameof method in my System.Linq | |
Console.WriteLine(name); | |
} | |
} | |
namespace System | |
{ | |
public static class Linq | |
{ | |
public static string nameof(Action x) => ""; | |
} | |
} |
こんな感じ。名前空間と同名のクラスを後から足してコード壊せる。というのを報告入れたら文法変わりました。
string interpolation と nameof は元々最近仕様が固まったもの。
nameof(MethodName) で、オーバーロードの弁別(2つオーバーロードがあるうちの、片方だけリネームかけた時にリファクタリングで追従できるか)については、結局、「できない」方向でいったん仕様を固めた見たいです(わかりやすい文法にならなくて前々から悩んでたけども)。なので、nameof は、現状、ローカル変数、クラス名、引数名、プロパティ名に対してはリファクタリングが効くものの、メソッドには効きません(ないメソッドを参照した時にコンパイルエラーにはなるので、ただの文字列よりはだいぶ有効)。
サロゲートペア識別子
C#は、識別子に使える文字をUnicodeのカテゴリーで判別しているわけですが。「○○Letter」カテゴリーなものはおおむね識別子に使えます。
𩸽(ほっけ)
Letterなのに使わしてもらえないかわいそうな文字もあるわけですが。
𠮷(U+20BB7、下の線の方が長い吉)とか、𠮟(U+ 20B9F、口偏に七の「しかる」)とか、𩸽(U+29E3D、魚の「ほっけ」)とか。いわゆる、サロゲートペア文字。char型が16ビットのC#とかJavaでは結構はまるやつ。
現状のC#は、サロゲートペアの識別子を一切認めていません。Roslynの実装でもそう。
ということで、こいつを見てくれ。
using System;
class
Program
{
static
void Main()
{
var
ᛊ = 2; // ルーン文字識別子。Other Letter。
var ɲ = 3; // 国際音声記号。Lower-case Letter。
var ˠ = 5; // 国際音声補助記号。Modifier Letter。
var
ℏ = 7; // プランク定数。Lower-case Letter。
//var ꬁ = 11; // エチオピア文字拡張A ってところに入ってる文字。Other Letter。Unicode 7.0 で入った。Roslyn なら識別子に使える。
//var 𩸽 = 13; // サロゲートペアで有名な「ほっけ」。現行の C# はサロゲートペア識別子を認めてない…
Console.WriteLine(ᛊ * ɲ * ˠ * ℏ);// * ꬁ * 𩸽);
}
}
ルーン文字(ᛊ)とか音声記号(ɲ)はおろか、音声補助記号(ˠ)まで識別子として使えるというのに。𩸽は無理。
UnicodeCategory GetUnicodeCategory(string s, int index)
Roslynは、C#で実装したC#コンパイラーです。ということで、.NETの標準ライブラリでのUnicodeサロゲートペアの扱いがどうかという辺りをまず紹介。
char型がGetUnicodeCategoryという静的メソッドを持っていて、これでUnicodeカテゴリーを判定できます。が、16ビットなchar型のメソッドで、どうやってサロゲートペアのカテゴリー判定をするのかというと、そのための別オーバーロードもちゃんとあります。string型を引数にとるもの。
using System;
class
Program
{
static
void Main()
{
Console.WriteLine(char.GetUnicodeCategory(‘ᛊ‘)); // OtherLetter
Console.WriteLine(char.GetUnicodeCategory(‘ɲ’)); // LowercaseLetter
// C# の char は16ビット。サロゲートペアは2文字になる。
Console.WriteLine(char.GetUnicodeCategory(“𩸽“[0])); // Surrogate
// ちゃんと、サロゲートペア用のカテゴリー判定メソッドもあって、こっちなら OtherLetter。
Console.WriteLine(char.GetUnicodeCategory(“𩸽“, 0)); // OtherLetter
}
}
これで判定してもらえれば、サロゲートペア識別子使えるのに…
使い道は
とはいえ、ここで問題。使えてうれしい?
ちょっと前に、Swiftが識別子に絵文字を使えるってので少しだけ話題になりましたが。その後、実用した人いるんですかね?【緩募】絵文字識別子の有意義な使い方(割と真剣に)。
Swiftの絵文字識別子って実際のところどうなんでしょう?探してみたら、Swiftの識別子の仕様説明してくれてるページは見つけたものの(Swift言語の識別子についての覚え書き)、これだと絵文字使えないように見えるんですが…
で、http://www.swiftstub.com/ とかを使っていくつかコードを書いてみたら、むしろ、サロゲートペアは何でも素通しで識別子に使えてる節があったり。
そしてしばらく試してみて、「使えてうれしい例」は全然思いつかないけども、「できたらまずそう」な例はボロボロ思いついてしまうなど。
やばい例その1: http://www.swiftstub.com/381749597/
let 💙 = 1
let 💚 = 2
let 💛 = 4
let 💜 = 8
println(💙 + 💚 + 💛 + 💜)
上から順に、青ハート、緑ハート、黄ハート、紫ハート。カラーフォント対応したもので見れば色で区別がつくはず。が、白黒だとやばい。この文章を書いているWordでの表示は全部黒い。一応、横線、↘向きの斜線、↗向きの斜線、縦線で区別はされているものの、結構近づかないとわからない。
やばい例その2: http://www.swiftstub.com/647829248/
let 𝟢 = 1
let 𝟣 = 2
let 𝟤 = 4
let 𝟥 = 8
let 𝟦 = 16
let 𝟧 = 32
let 𝟨 = 64
let 𝟩 = 128
let 𝟪 = 256
let 𝟫 = 512
var x = 0
x += 𝟢
x += 𝟣
x += 𝟤
x += 𝟥
x += 𝟦
x += 𝟧
x += 𝟨
x += 𝟩
x += 𝟪
x += 𝟫
println(x)
「Mathematical Alphanumeric Symbols」って言って、U+1D400-1D7FF辺りに、数式で使う用の、フォント指定付きのアルファベットや数字があります。上記コードの0は、リテラルの方が普通の数字、変数に使ってる方が「MATHEMATICAL SANS-SERIF DIGIT」(サンセリフ フォント指定の数字)の𝟢(U+1D7E2)。コンパイル通った… 𝟢って書いたら0じゃなかった。何を言っているかわからねぇと思うが、書いた本人も後で見てわかる気がしねぇ。
カテゴリー判定は必須として
やばい例を避けるには、カテゴリー判定は必須だと思うんですが。
using System;
using System.Text;
class
Program
{
static
void Main()
{
ShowCategory(“𩸽“); // 𩸽 (U+29E3D): OtherLetter
ShowCategory(“𝟢“); // 𝟢 (U+1D7E2): DecimalDigitNumber
}
static
void ShowCategory(string s)
{
var bytes = Encoding.UTF32.GetBytes(s);
var x = (bytes[0] << 0) | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
Console.WriteLine(“{0} (U+{1:X}): {2}”, s, x, char.GetUnicodeCategory(s, 0));
}
}
それはそれで。MATHEMATICAL SANS-SERIF DIGIT ZERO (U+1D7E2、𝟢)が普通に10進数扱い。ASCII文字の方の0と一緒。つまり、下手なことをすると、識別子2文字目以降に使える。
var x0 = 10; // ASCII の 0
var x𝟢 = 20; // U+1D7E2
これがコンパイル通るのはまずそう。なのでさらに、制限が必要そう。
ありえそうなのは、Unicode互換文字自体をはじくとか。でもそれをやると、最初の方で例に挙げた ℏ (U+ 210F、プランク定数)とかも使えなくなって、既存コンパイラーの挙動壊す。
もう1つできそうなのは、識別子の一意性判定にUnicode正規化を掛けるとか。U+1D7E2の方の𝟢は、Compatibility Decompositionで正規化するとASCIIの方の0になるので、「ぱっと見同じナノに別変数」みたいなのはできなくなるはず。
コスト/メリット合う?
何でこんなことを考えてるかというと、そもそもは、Roslynに対して絵文字対応とか提案できないかなぁとか思ったのがきっかけです。で、提案するからにはメリットがないと行けない。が、考えてみても特にメリット思い浮かばず、やばい例は思いつき、やばいものを避けるには結構コストがかかりそう(サロゲートペアのカテゴリー判定とか、識別子の一意性判定前に正規化とか)。そして何よりも、絵文字のカテゴリーはOther Symbolなので、カテゴリー判定すると識別子に使えないカテゴリー。絵文字は無理というかヤバいとしても、せめて𩸽だけでも…と思ったものの、それでもこのコストには見合うのか。特に、RoslynはIDE上でリアルタイムに動かす都合上、コンパイル速度に対して結構シビアなので。
うん、無理(いまここ)。
ということで、割かし真剣に
【緩募】絵文字識別子の有意義な使い方
【緩募】𠮷、𠮟、𩸽を識別子に使いたい実例
あけましておめでとうございます
よい正月休みでした(引きこもりのいう「よい」とは、家から一歩も出ずに済んだ幸せのことです)。
なんか、そこそこまとまった分量一気に書いたの久しぶりな気がする。
ちなみに、最後の1個は昔ブログで書いたものの移植。本体記事にあってもよかったかなというか、最初からあっちに出せばよかった。
イベントがらみの話を書こうと思ってたはずが、気が付いたらボックス化とか弱参照とかの話にも手を出していたり。どうしてこうなった。まあ、いずれ書こうと思っていた内容なのでいいんですけども。
イベントの取り扱いはほんといろいろ悩ましい。C#でってことじゃなく、他の言語でやろうときっと似たようなものですが(add/removeなものばっかり。言語によっては標準で弱イベント購読提供してますが、それはそれで性能を犠牲にしていたり)。とりあえず、マシなのはRxを使うことなんですが…
そういえば、これを見た業務系Javaな人曰く「Javaいじめですか!」って言われた。そんなつもりはなく… Javaにはさらにソフト参照とかファントム参照とかありますし… 最近RxJavaが結構はやりみたいですし…