++C++; // 未確認飛行 C ブログ

http://ufcpp.net/

Scalaの機能

leave a comment »

以下のような記事が。

ちなみに、ことの発端は以下の記事。

これと全く同じことをC#版作って、昔Wordでやった、わざとあおり文書いて炎上マーケティングやってやろうかなどという黒いことも考えたものの、C#とScalaってあんまりダイレクトに比較できそうになく断念。

 

で、結局、C#とScalaの差分にあたる部分がどうなのか、本当に欲しいのか、欲しいならどういう形で入るのが良さげなのかとか考えてみたり。

あくまで個人的意見として。

Actor

直接の競合

.NET関連で構文からして近いのはAxumかな。C#とは別言語だし、正直、これがそのまま製品レベルになる気はしておらず・・・

製品になりそうなもので、かつC#で使えるものだと、一番近いのはたぶん、TPL Dataflowっていうライブラリ。このライブラリ自体は、おそらく.NET 5に入る。これを使いやすくするための構文糖衣がC#に入るかというと、大分先になりそうな予感。

でも、どうなんだろう、Actor

実はあんまりActor型の同時実行を使う必要性感じてなかったり。同時実行とか並列が必要な場面と、それに対するC#の対応方法というと、以下のような感じ。

目的

概要

C#の対応方法

UIスレッド

GUI関連は単一スレッドで実行しないといけなくて、かつ、UIスレッドで重たい処理してしまうとUIがフリーズ。

メッセージポンプとディスパッチャーを使う。

大半は次項のTask非同期で解決可能。

非同期I/O

重たい処理の結果受け取り

BeginXxx, EndXxx(Asynchronous Programming Pattern)とかXxxAsync, XxxCompletedイベント(Event-based Asynchronous Pattern)とか、めんどくさいです。

Task非同期

内部的な実装は、イテレーターの応用とTaskの継続渡し。

同上、ちなみに、F#の場合

 

Computational Expressionsってのを使えば、C# 5.0のTask非同期と似たようなことできる。

C#的に言うと、

var x = HeavyWork();


DoAsync(HeavyWork, x => { 継続処理 });

に置き換えて実行する構文。

大量データの並列処理

マルチコア利用による高速化。

ParallelPLINQ

for文をParallel.Forに置き換えるだけ。

LINQにAsParallel()付けるだけ。

非同期イベントをストリーム的に受け取る

イベントって、非同期に、何度も来る。Task非同期の場合は、値の受け取りは1回きりという前提。

Reactive Extensions

物理的なマシンをまたいだ分散並列処理

物理マシンまたぐためには、根本的に、ActorとかDataflow的な処理をせざるを得ない。

Dryad

LINQで処理書くだけで分散。

 

パターンマッチ

これは素直にすごく欲しい。C#のswitch文はダメな子。

でも、パターンマッチが欲しい状況は限定的かもしれない。さしあたって、C#にこの手の文法足さずとも、部分的にF#使うので事足りるかもとか思ったり。

少なくとも、OOP的な仮想関数テーブルの方がいいような状況でパターンマッチ使うのは、if-else地獄とそう変わらないと思う。

ラムダ短く掛ける

この辺りは「仕方がない」かな。

ラムダ式単体で見れば、いくらでもよさげな文法思いつくけども、他の文法との整合性ってのも必要なので。ラムダ式の構文を変えるなら、普通のメソッドの定義の構文も変えたい。そしてそれは、C++ 0xがやろうとしてて、賛否両論。

_ に特殊な意味(その引数は無視)を与えるの(というか、この手の暗黙のルールと、記号に特殊な意味与えすぎるの全般)はあんまり好きじゃないのだけど、Scalaみたいな言語の場合はどのみちパターンマッチで _ が必要だし、そっちとの一貫性考えるとありかな。

Tuple

Tupleが便利になるのはパターンマッチあってこそだと思うので、これに関しては割愛。パターンマッチのとこ参照。

Map→Map、List→Listの高階関数

LINQ(IEnumerable→IEnumerableの高階関数)があればOK。というか、そっちの方が好み。

ジェネリクス関連

これはそもそもJVM VS CLRな話でもあり。JVM、バイトコード互換性にこだわり過ぎ。

言語的な話でいうと、ジェネリックな型エイリアス:

using List<T> = System.Collections.ObjectModel.ObservableCollection<T>;

みたいなのはかなり欲しい。

ついでに言うと、それをクラスの中で書けるようにして欲しい。

他は微妙。

型の下限指定は、in/out付けて反変/共変にする以上のことで役に立つ場面がそんなに思い当たらず。

型推論がちょっとだけ高機能

戻り値の型省略には否定的。メソッドは先頭行の宣言部分だけ見てシグネチャ判断できて欲しい。

2つほどC#の型推論で不満をいうなら、デリゲートをデフォルトでFunc<int, int>にして欲しいのと、右辺値からの型推定は欲しいかも。

前者は、

var f = (int X) => X * X;

みたいなのがコンパイル通らないのを何とかして欲しい。後者は、

static T F<T>() { ... }

みたいなジェネリック メソッドがあるとき、

int x = F();

を認めて欲しかったりも。

import文

これはそもそも、JVMの、名前空間と物理パス構成がリンクしちゃってるpackageって概念自体がちょっと・・・

ただ、どこでもusing宣言(クラス内でusing System; とか書きたい)ってのはちょっと欲しい。

structural subtyping

これは必要なのよね・・・

アセンブリの依存関係を作らず、コンパイラーによる型チェックとか、IDEによる補完機能とかを享受しようとすると、こういう概念が必要。

WPFのデータ バインディングとか、中身が動的で型が緩すぎて泣きそうになるし。にはContent Classっていう似たようなことできそうな機能あったのだけども。

ただ、こういうスキーマ的なものを、その言語自身で書けてしまうと、結局それ書いた部分に依存が生まれちゃうのよね・・・。C#内にこういう機能持つんじゃなくて、もう1段階抽象的な何かが必要かも。

REPL

Compiler as a Service待ちなのよね・・・いつになるんだろう。

REPLできることよりは、アプリケーションに組み込めるとか、言語内DSLへの道ができることの方が可能性広がるんだけども。

なにぶん、自分個人としてはほぼ常時Visual Studio立ち上がってるのでREPLが必要になる機会はそうなく。1ラインで書きたい場合はPowerShell。ただ、PowerShellは、これはこれで結構癖のある文法してるので、C#な人に全てに無条件にお勧めできるわけではなく・・・

STM

ボツっちゃったね、STM.NET

まあ、Task非同期ならそもそもlockが必要ないわけで。軽量なatomic実行の手段提供するよりも、極力lock避ける実装した方が高速だし安全なのも当然で。

Immutable

いや、欲しいんだけども、immutable関連の機能。

ただ、気を付けたいのは・・・

  • varとvalで区別(1文字違い、かつ、lとr)とか、それはさすがにないだろ
  • 変数だけをimmutalbeにしちゃダメ
    • クラスの方のimmutable(フィールド書き換え不可)を保証できないものを、変数だけimmutableにしても無駄 or 混乱を招く

という辺りが問題で。

case classみたいなもの(かつ、case classのメンバーはvalなことを強制)とセットでないと意味なさげかなぁと。

LINQのletでimmutableにできるよってのは、ある意味正しいのかもしれない。Immutableが欲しい文脈とLINQ使う文脈って割と近いので。そして匿名型(immutableになってる)使いまくると。

コンストラクターの構文

Scalaだと、クラスの定義自体が一種のコンストラクターになっていて、C#みたいにメンバー初期化とコンストラクター内の初期化の2つに分かれてない。

これは欲しいような欲しくないような。

実は、C#において、

class Sample
{
    int x = 1;
    int y = 2;
}

ってのと、

class Sample
{
    int x;
    int y;
    public Sample() { x = 1; y = 2; }
}

っての、実行のされ方が違うんですよね。C#のコンストラクターは、以下のような処理順になってます。

  • メンバー初期化子でフィールドを初期化
  • 親クラスのコンストラクターを呼び出す
  • 自身のコンストラクターを呼び出す

親クラスのコンストラクターで仮想メソッドを呼んだとき、変数の値が変わるわけです。

If式、try-catch

三項条件演算子、そんなに見にくい?としか言えず・・・

C#でifとかtry-catchを式にしたければ、まずvoidの扱い考え直さないと・・・というのもあり。

Implicit parameter

暗黙的型変換とか、今のC#のimplict構文すらなくしてもいいくらいだと思うのに、それを使ってメソッドの後置き構文実現とか、これはあり得ない・・・

Trait

こういう機能が欲しいことはあるものの、scalaみたいにobject X with Traitでやりたいかと言われると微妙。

これよりは、Go言語みたいな、包含による処理の委譲(Goの場合は、structに匿名フィールドを定義すると、そのフィールドのメンバーをそのまま取り込める)の方が好み。

Case class

パターンマッチ用途に関してはすごくよさげ。

あと、C#でもImmutableなフィールドだけを持つクラスを簡単に作りたいことは結構ある。今の匿名型の構文を名前付きにしたいというか。

ただ、classとcase classの混在が紛らわしくてちょっといや。Case classっていう名前が悪いのか、こういう機能はC#よりも1段階抽象度の高い層(データ定義層的な?)でやるべきなのか・・・

メソッド名に記号使える

可読文字以外を識別子に使うのってなかなかに勇気が必要で。似たようなグリフで違う意味な文字だらけだし・・・

あと、今のC系言語(C、C++、Java、C#、etc.)のa+++b問題(a+(++b)?(a++)+b?)みたいなこと頻出しそうなのも・・・

それよりは、「Unicodeで演算子カテゴリーに入ってる文字を演算子オーバーロードで使える」とかの方が個人的には欲しかったりも。

returnとかセミコロンとか余計なカッコ省略

C#でもラムダ式だとこの手の省略ができるわけですが。メソッドの書き方も変えたいけども、今からじゃ無理よね。C++ 0xはよくやるなぁと思う。

あと、これも、voidの扱いが微妙だったり。

Func<intint> f = x => x * x;

Func<intint> f = x => { return x * x; };

の略(returnと{}の省略)だけども、

Action<int> f = x => Console.Write(“({0})”, x);

Action<int> f = x => { Console.Write(“({0})”, x); };

の略(省略されてるのは{}だけ)だったり。

FuncとActionが分かれちゃってるのもvoidの扱いが特殊なせいで、この辺りはNothing的なものが欲しく思ったり。

シングルトン

静的メソッド置き場以上な感じのシングルトンが欲しい場面、どのくらいあるかな・・・という気もしたり。

WPFとかで、いちいち(App)Application.Current書くのもばかばかしいとは思うのだけども。

コンパイラ プラグイン

これもCompiler as a Service待ちかな。

この手のコンパイラの挙動変更してしまうものは恐ろしくもあり、言語内に入れてしまうべきものなのかどうかは迷う。

それよりは、C#でいうと、Visual Studioへの組み込みと、ビルド時コード生成の方がいいのかなぁなどと。

オーバーフローのチェック

これはJVMの問題。

構造体

Javaの、組み込み整数型だけ特別扱いな実装はいまいちに思う。構造体はあって欲しい。

ただ、C#においても、内部挙動わかってる人でないと構造体は使いあぐねる(immutableに作らないと混乱の元、16バイト未満なサイズでないとコピーコスト大という指針知ってないといけない)ものなわけで・・・。ないと困るんだけども、あんまり表立って推したい機能でもない。

unsafe文

.NETのネイティブ相互運用が楽なのは、P/Invoke回りの命令をCLRが最初から持ってるからで、unsafeよりはそっちの方が大きいかも。

一応、極端にパフォーマンスが必要な状況下ではP/InvokeなしのC#(マネージに完結した環境)でもポインターを使いたいことはなくはないけど、超レア。

Internal

Javaってなんでinternal(assembly)とprotected(family)わけなかったんだろ。というレベルで、必須なものだと思うのだけど。

参照渡し(ref とか out)

P/Invoke専用(と言い切れるといいなぁ)。多値戻り値さえあれば不要なのに・・・

とか思うけども、lockみたいな機構を本当にちゃんとやろうとしたらrefが必要とかいう話も聞いたようなことが。

Event

AddListener/RemoveListener地獄マジ勘弁。

まあ、じゃあ、C#のeventの+= -=がいいのかと言われると・・・

Reactive ExtensionsみたいにDisposableでイベントのunsbscribeすべきなのかもしれない。

xmlリテラル

VBェ・・・

汎用言語の組み込み機能としては要らないものだと思う。

言語内DSLを気軽に使える時代が来たら、文脈限定で使いたいことはたぶん多々ある。

Written by ufcpp

2011年2月14日 @ 13:17

カテゴリー: .NET, C#

Tagged with ,

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。