いろんな言語のラムダ式とキャプチャ

javaの無名関数がdisられているらしいので他の言語と比較してみた。
http://www.infoq.com/jp/news/2010/06/lambda-syntax-debate

引数に整数型を取り + 1 して返す無名関数を定義してみる。
目的は 72 という数字を 変数 i に格納すること。

なるだけ省略表記を使わないで作るよ。
間違っていたらごめんね!!

いろいろ間違っていたので結構直しました!!

java

・無名ではない関数の場合

int f(int x)
{
	return x + 1;
}

・定義してから呼ぶ

#int(int) f = #(int x)(return x + 1);
int i = f.(71);  //f「.」(71) となっているところが特徴的

・↑を省略化して書く

#int(int) f = #(x)(x + 1);
int i = f.(71);

・定義と同時に直接呼ぶ

int i = #(int x)(return x + 1).(71);

・おまけ:キャプチャ
、、、どうやるんだろう。

多分こんな感じすか?

int cap = 1;
int cap2 = cap;
#int(int) f = #(int x)(return x + 1 + cap2);
cap = -100; //ぶっ壊す
int i = f.(70);


参考:
http://mail.openjdk.java.net/pipermail/lambda-dev/attachments/20100212/af8d2cc5/attachment-0001.txt

注意:
動く実装がないから間違っているかも知れぬ。

C++0x

・無名ではない関数の場合

int f(int x)
{
	return x + 1;
}

・定義してから呼ぶ

std::function<int (int)> f =  [](int x) -> int { return x + 1; };
int i = f(71);

//iの値は 72

・↑を省略化して書く

auto f =  [](int x) -> int { return x + 1; };
int i = f(71);

//iの値は 72

・定義と同時に直接呼ぶ

int i = ([](int x) -> int { return x + 1; })(71);

//iの値は 72

・おまけ:キャプチャ

int cap = 1;
auto f =  [cap](int x) -> int { return x + 1 + cap; };
cap = -100;	   //ぶっ壊す
int i = f(70); //だけど保持される

//iの値は 72

参考
http://ja.wikipedia.org/wiki/C%2B%2B0x#.E3.83.A9.E3.83.A0.E3.83.80.E9.96.A2.E6.95.B0.E3.81.A8.E3.83.A9.E3.83.A0.E3.83.80.E5.BC.8F
http://codezine.jp/article/detail/4035

C# (3.0以上)

・無名ではない関数の場合

int f(int x)
{
	return x + 1;
}

・定義してから呼ぶ

Func<int, int> f = x => { return x + 1; };
int i = f(71);

//iの値は 72

・↑を省略化して書く

Func<int, int> f = x => x + 1;
int i = f(71);

//iの値は 72

・定義と同時に直接呼ぶ

int i = ((Func<int, int>)(x => { return x + 1; }))(71);

//iの値は 72

・おまけ:キャプチャ
、、、、どうやるんだろう?

//これでは無理でした。
int cap = 1;
Func<int, int> f = x => { return x + 1 + cap; };
cap = -100;	   //ぶっ壊す
int i = f(70); // 70 + 1 + 1 ではなく、 70 + 1 + (-100) で -29 になってしまう

//iの値は -29

これらは参照で渡されるので事前に別名に保存すればOKらしい。

int cap = 1;
int cap2 = cap;
Func<int, int> f = x => { return x + 1 + cap2; };
cap = -100;	   //ぶっ壊す
int i = f(70); 

//iの値は 72


参考:
http://ufcpp.net/study/csharp/ap_ver3.html

PHP (5.3以上)

・無名ではない関数の場合

function f($x)
{
	return $x + 1;
}

・定義してから呼ぶ

$f = function($x)
{
	return $x + 1;
};
$i = $f(71);

//iの値は 72

・定義と同時に直接呼ぶ
、、、、どうやるんだろう?

//これはエラーになる。
$i = (function($x){ return $x + 1; })(71);

・おまけ:キャプチャ

$cap = 1;
$f = function($x) use($cap) 
{
	return $x + 1 + $cap;
};
$cap = -100; //ぶっ壊す
$i = $f(70); //だけど保持される

//$iの値は 72

参考:
http://php.net/manual/ja/functions.anonymous.php

javascript

無名ではない関数の場合

function f(var x)
{
	return x + 1;
}

・定義してから呼ぶ

var f = function(x)
{
	return x + 1;
}
var i = f(71);

//iの値は 72

・定義と同時に直接呼ぶ

var i = (function(var x){ return x + 1; })(71);

//iの値は 72

・おまけ:キャプチャ
、、、、どうやるんだろう?

//これではキャプチャできない。。。
var cap = 1;
var f = function(x)
{
	return x + 1 + cap;
}
cap = -100; //ぶっ壊す
var i = f(70); // 70 + 1 + 1 ではなく、 70 + 1 + (-100) で -29 になってしまう

//iの値は -29

コレも同じく別名に保存しておく。

var cap = 1;
let cap2 = cap;
var f = function(x)
{
	return x + 1 + cap2;
}
cap = -100; //ぶっ壊す
var i = f(70);

//iの値は 72

テスト環境: SpiderMonkey 1.8.0

まとめ

//java
#int(int) f = #(int x)(return x + 1);
int i = f.(71);  //f「.」(71) となっているところが特徴的

//C++0x
auto f =  [](int x) -> int { return x + 1; };
int i = f(71);

//C#
Func<int, int> f = x => x + 1;
int i = f(71);

//PHP
$f = function($x)
{
	return $x + 1;
};
$i = $f(71);

//javascript
var f = function(x)
{
	return x + 1;
}
var i = f(71);

どーでもいいけど、無名関数って、無名剣無明剣(ロマサガの最強の大剣技)と名前がかぶっていてかっこいいよね!!

無名関数!!