twitterで見かけた話。きっかけはSwiftのものなんですが、「Commonly Rejected Changes」、つまり、「頻繁にリジェクトされる変更の提案」集がまとめられてるみたいです。これを見た感想は「ああ、あるある、C#でもよくある」だったので、それをネタにしてみようかと。
{} をやめて、Python風のインデント構文がほしい
これ、SwiftやC#に限らずありとあらゆるプログラミング言語で発生すると思うんですが、必ず出てくるんですよね、インデントでブロックを切る構文を求めてくる人。SwiftにしろC#にしろ、基本方針として「空白文字を除外しても意味が変わらない」を採用している言語に対してそういう要求をされましても…
まあ、Swiftは「空白を抜いたら意味が変わる」構文あるんですけどね。?:
の?
の前にスペースを入れないと、型名?
の?
と区別がつかないそうで。
それを言い出すと、C系言語共通で、a+++b
の解釈は空白の入れ方によって変わってしまうわけですが。
セミコロンなくして
同上。
「空白文字を除外しても意味が変わらない」方針と相性悪いんですよねぇ、セミコロンlessプログラム。 改行のあるなしで実行結果が変わることがあるとか、割かし悪夢を生みます。
逆に、「改行区切り」の代表格、Visual Basicなんかは、改行を挟めない(挟めなかった)ことでいろいろ苦労していますし。
記号が分かりづらいから止めてほしい
2件ほど。
&&
と||
の代わりにand
or
とかにしてほしい- 条件演算子
? :
はわかりにくいからやめてほしい
いずれも、本質は「記号が分かりづらい」だと思います。
これはわからなくはないもの。「式」=「演算子」=「記号」ってのは、C言語の悪い癖な感じもします。確かに初見の人には優しくなく、googlabilityも悪い。
でも、そのために予約語(= 変数名などに使えない)を増やすの?とか、C言語をすでに知ってる人の数が多いのでわざわざ変えるメリットも低いとかあり。
if/elseとswitchを式にしてほしい
if/elseは、前節の「? :
が記号だからわかりづらい」問題と同義でしょう。「if/else相当の式」は? :
でできる話なので。
switchは、C#だと7で式バージョンのswitchが入る方向で議論進んでいます。
C#の場合は、これまで、if/elseやループに相当する式は書けたもののswitchはなかったので。
ステートメント | 式 |
---|---|
if/else | '? : ' |
foreach | LINQ |
switch | switch (C# 7向け提案) |
これまではswitchの利用頻度がそこまで高くなかったのでそんなに欲しいとも思わなかったものの、C# 7では別途パターン マッチングで使えるようにswitchステートメントを拡張する予定なので。そうすると「switch式」もほしくなるだろいうということで、一緒に提案されています。
ただ、こうなるとますます「? :
が記号だからわかりづらい」というのが分からなくもない話に。
switchは、ステートメントでも式でもswitch
キーワードを使います(式はもしかしたらmatch
キーワードになる可能性もあるもの、いずれにしても記号ではなくて英単語)。
なので、if/elseの式バージョンも、if/elseっていう英単語の方が分かりやすかったりしないかなぁとは少し思います。
まあ、今更の変更は無理ですが。
Swiftを使ってSwiftコンパイラーを書き直して
C#も10年くらい言われ続けました。C#の場合はそれがRoslynなわけですが、これがどれだけ大変だったか。
実際のところ、「既存のプログラムと互換性を保ったものを、別の言語に移植」というのはかなり不毛な作業です。よっぽど強い動機がなければできない。C#の場合は以下のような動機がありました
- さすがにC++製コンパイラーだと機能追加が苦しくなってきた
- Visual Studioとの連携(コード補完、静的コード解析、リファクタリング)の高機能化が難しかった
が、これも「10年越しの実現」です。「そろそろ苦しい」が「移植の不毛さ」を上回るのにそれくらいの歳月がかかっています。
また、Roslynの完成は相当待たされました。理由は、以下のようなものです。
- 他部署からの要望(C#の場合はWindows 8関連、つまり、Windows Runtime APIと非同期処理への対応)に時間を取られて、なかなか「単なる移植」には人員を割けなかった
- 「単なる移植」で数年、言語の進化を停滞させるのもつらい
- 実はバグだった挙動も含め、元のコンパイラーの挙動を変えると、世の中に出回っているコードを壊すので、そこの互換性確保が結構つらい
こういうハードルがあって、結局、「C#コンパイラーのC#化」に取り掛かってから、リリースまでに5・6年はかかっています。C#自体の発表から数えると、15年の歳月をかけてやっと「C#化」されました。
クロージャの構文を変えてほしい
これは、C#だとあんまり言われないんですよね。みんな、ラムダ式におおむね満足しているようで。
多少の提案はあったりはするんですが。
- 引数を別に使わない場合に省略したいという類
-
ローカル変数のキャプチャの仕方を制御したい
- C++ 14のラムダ式みたいなやつ
- 参照で取り込み、値のコピーで取り込みを選びたいことがある
- 取り込んだ変数の書き換えの可否を制御したいことがある
- C#のは常に、参照で書き換え可能
シングル クォートの文字リテラルがほしい
Swiftって文字リテラルと文字列リテラルの区別ないんですね…
これはでもなかなか難しい問題でして。特に、1文字が何バイトになるか全くわからない現在となっては。
マイクロソフト内部でC#を作り始めた当時(だいたい1998年頃)は、Unicode出始めの時期、つまり、まだ16ビットですべての文字を表せるという幻想があった頃です。なので、char
型は16ビットだし、string
はそれの配列に皮を被せたような構造。
ですが、今はどうかというと。サロゲート ペアがあり、結合文字があり、異体字セレクターがあり。最近だと、絵文字がなかなか来てます。肌色(異体字)セレクターと結合の組み合わせで、「色白男性と色黒女性の家族」みたいに、1文字で表示されるけどもデータ上は何バイトも使う文字すらあります。
結局、世の中の主流派UTF8、つまり、可変バイトの文字列符号化でして。Webでレガシーとの互換が必要ないものだと、ほとんどのテキストがUTF8で流れてるんじゃないですかね。となると、C#でパフォーマンス的にネックになりがちなのが、UTF8からstring
への変換処理だったりします。その結果、今、string
とは別に、System.Text.Utf8.Utf8String
なんていうクラスを別途実装中だったりします。この場合、16ビットなchar
は大して意味をなさなかったり。
continueキーワードを、スクリプト言語でみられる他のキーワードに置き換えてほしい
これもC#だとあんまり言われないですね。
まあこれ、「自分が慣れた言語に近づいてほしい」欲なんですかねぇ。C#の場合は名前にCという文字がはいってるのもあって、「C系文化」から外れようという提案は少な目なんですが。Swiftは結構「脱C」しているのでこういうこと言われてしまうのかも。
switch 中で、default の代わりに case _ を使いたい
C#では、C# 7でパターン マッチングが入って、その仕様の中に case *
で任意のパターンにマッチというのを作れるので、確かにdefaultとの住み分けはどうなるんだろうって思います。まあでも、C系言語に脈々と受け継がれてきたdefaultの使い方を変えるだけの価値があるかと言われると。