ツクールMVでLINQってみる

やあよい子のみんな!
ニートだよ!

今日はねぇ。
みんな大好きLINQをツクールMVで使ってみるのさ!

LINQってなんやねん

はい、疲れたので普通のテンションになります。
LINQってなんやねんということですが、.NET Frameworkで使われている技術です。
C#で人気ですね。Unity使ってる人には馴染みがあると思います(たぶん)。
小難しいこと知りたい人はググってください。

そして最初に書いておきますが、僕はLINQ自体を使い始めたのも最近ですし、あとで紹介するlinq.jsを使い始めたのは二時間前です。
つまりあんまり情報を鵜呑みにするのはよろしくないです!
必ずご自分で確認してください。
内容に明らかな間違いがあれば、Twitterかなんかでそっと教えてください。
修正記事くらいは上げると思います。

LINQで何ができねん

例えば1から1000の整数を配列にぶっこみたいとき、どうしますか?

var array = [];
for(var i = 0; i < 1000; i++){ array.push(i); }

なるほどよくありそうなコードです。
では、偶数だけをぶっこみたいときはどうしましょう?

var array = [];
for(var i = 0; i < 1000; i++){ if(i % 2 === 0){ array.push(i); } }

ふむふむ。
こうですかねえ。
じゃあ、さらに、この中から値に4を含むものだけをぶっこみたいなら?

var array = [];
for(var i = 0; i < 1000; i++){ if(i % 2 === 0){ if(String(i).contains('4')){ array.push(i); } } }

ワオ!
大変!
コレハイケナイ!

あとから読み直すとき、何をやっているのか理解するのに時間もかかりそうです。

LINQを使う

LINQを使って書くと、上記と同じことがこうできます。

var array = Enumerable.range(1, 1000).where("n => n % 2 === 0").where("n => n.toString().contains('4')").toArray();


ワオ!
簡単!
スバラシイ!

linq.jsの導入

導入方法とかの詳しい説明はその辺中で解説されてるので、ちょっとだけしか書きません。
まずはこちらからlinq.jsを入手してください。
https://github.com/mihaifm/linq
linq.jsを普通のプラグインと同じように導入して、VSCodeを使っているなら「linq.d.ts」をプラグインのフォルダにぶっこんでください。
これでインテリセンスも働きます(他のエディタでも動くかも)。

はい以上。

LINQなにやっとんねん

C#に馴染みがある方なら、以下のコードが何をやっているのか類推できると思います。

var arrary2 = Enumerable.range(1, 1000).where("n => n % 2 === 0").where("n => n.toString().contains('4')").toArray();

が、ツクールMVをやっている方みんながみんなC#をやっているとは到底思えないので、ちょこっとだけ解説してみます。
ちなみに僕はつい先日LINQを始めたLINQ初心者です。
その辺ご了承ください(つまり間違ってることを平気で書くかもしれない)。

まず

Enumerable.range(1, 1000)

これは1~1000の値を持つシーケンス(JavaScriptの場合、多分中身でやってることは違う気がしますが)を生成していることになります。
これはなんとなくわかりますよね。
要は1~1000の値を持つナンゾを作っているだけです。

で、次のこれ。

Enumerable.range(1, 1000).where("n => n % 2 === 0")

一体何じゃラホイ!?
と思う方も多いと思います。
whereは「条件を満たす要素だけを取り出す」という意味です。
中身のダブルクォーテーションでくくられているのは、ラムダ式です。
JavaScriptのアロー関数に近いですね。
確認していませんが、ツクールMVではアロー関数は利用できないらしい(どっかにそう書いてた)のですが、これは内部的にはアロー関数ではないため、普通に使えます。
いや、環境によっては使えないかもしれませんが、たぶん大丈夫です。

意味的にはこんな感じです。

function(n) {
if(n % 2 === 0){
return true;
}
}

なんか見えてきません?
見えませんか?
そうですか……。

要は無名関数

上記のラムダ式は、要は無名関数です。
実際、例で示したラムダ式をJavaScriptでよくある無名関数(前の節で示したコード)にそっくりそのまま変えても、同じ結果を示します。
「じゃあ、ややこしいし、ラムダ式とかやめて普通の無名関数使えばよくね?」と思うかもしれませんが、慣れたらラムダ式の方が絶対に楽です。
いや、僕はまだ全然LINQに慣れていないのですが、そんな僕でさえラムダ式のほうが圧倒的に楽なのですから、わざわざ通常の無名関数を使う理由はゼロです。

ちなみにですが、上記の例は式形式のラムダ式です。
ステートメント形式のラムダ式もあるのですが、どうもlinq.jsではうまく動きませんでした
ステートメント形式を使いたい場合は、おとなしく通常の無名関数を使いましょう。

注*ステートメント形式のラムダ式が使えないというのはちょっと考えにくい気もするので、僕のやりかたがまずくて動いてないだけの可能性がおおいにあります。

var arrary2 = Enumerable.range(1, 1000).where(function(n){console.log('一個処理挟むぞい!'); return n % 2 === 0;}).where("n => n.toString().contains('5')").toArray();

こんな感じですね。

whereに挟むのは単純な処理が多いと思うので、ラムダ式を使うと楽ですよーという感じです。
それ以上の深い意味はありません。

解説にもどる

解説の続きに戻ります。

Enumerable.range(1, 1000).where("n => n % 2 === 0").where("n => n.toString().contains('4')")

後半のwhereですね。
これもラムダ式を使っています。
ここのnには、先ほどのラムダ式でtrueが返ってきたもののみが渡されます
つまり偶数です。
偶数を文字列に一度変換し、文字列型のcontainsメソッドを使って、4を含む数字を取り出しているわけですね。
最後のtoArray()は、配列に変換しているだけです。
このメソッドを用いることで、配列として扱うことができるようになります。

以上です。

もっと複雑な例

「わりとめんどくねえ? 普通にループでよくねえ?」
と思った方もいるかと思います。
では、もうちょっと複雑な例を紹介します。

例えばこんなブックリストがあったとします。

var bookList = [{title:'若草物語', price: 500},{title:'千夜一夜物語', price: 1000},{title:'嵐が丘', price: 600}];

このブックリストのtitleプロパティに「物語」が含まれている本がいくつあるか調べたいとします。
従来の方法でもできますが、わりと面倒ですよね?
LINQを使えばこうです。

var count = Enumerable.from(bookList).count("book => book.title.contains('物語')");
console.log(count);//2

わお!
シンプル!

では次は、550円以上でかつ、タイトルプロパティだけを持つオブジェクトの配列を新たに作りたいと思います。
このとき、ついでに安い順から表示することにしましょう。
LINQなしだと面倒ですが、LINQを使えばあら不思議。

var story = Enumerable.from(bookList).orderBy("book => book.price").where("book => book.price > 550").select("book => {title : book.title}").toArray();

ワオ!
簡単!

LINQは奥が深い

例に示したコードは、たぶんもっとシンプルにできる気がします。
僕自身まだLINQを勉強し始めたばかりなので、サンプルコードを書くのにも四苦八苦しましたw
LINQだけで一冊の本ができるほどなので、これから徐々に勉強していきたいと思います。

ちなみにですが、C#のLINQ拡張メソッドには遅延実行するものと、即時実行するものがあります。
これがLINQのミソの一つなのですが、linq.jsが遅延実行しているのかどうかは謎です。
また今度調べてみますが、たぶん遅延実行してるんじゃないかなーと思いました。
この辺の用語については、もうちょっとlinq.jsを使い込んでから書きたいと思います。
あとググったら情報たくさん出ます。

ツクールMVでの使いどころ

最後になりましたが、ツクールMVでの使い所は一体どこか?
と言えば、一般に公開する自作プラグインの制作には使えません
なぜなら、プラグイン使用者にlinq.jsのインストールを強制することになってしまうからです(ちなみにMITライセンスです)。
なので、自作ゲームをスクリプトを使ってバリバリ作りたいぜ!
という方が楽をするために使えるくらいかなーと思いました。

ほな、こんな感じで。

フォローする