Integrated Dynamics: Operatorの落とし穴 (1.18.2/ ITs included)
前置き
問題解決の熱が冷めない内に書き留めたいので基本的に筆者主観であることをご了承下さい. 余計な情報を含む可能性があります.
言い方はアレですが, Operatorに挙げられるような動的関数を使用したことがこれまでになかった僕のようなチンパンの皆様に捧げる記事です. Integrated Dynamicsと和解せよ
導入: Operatorの引数
Integrated DynamicsのOperatorなのですが, これが読みづらい.
基本的には A(入力) -> B(出力) という記法が取られていますが
Operatorが担う処理は多岐に渡るため, 当然このような物が現れます.
A -> B -> Cとすると, これはBに指定されるキーが持つ値をAというNBTからDoubleとしてCに出力すると解釈できます.
どのような罠であるのか理解するための前提知識として, 基本的なIntegrated DynamicsでのOperatorの使い方について知っておく必要があります.
知識: Operatorはどう使うのか
Operatorの主な用途はfilterとmap(と, reduce)になります.
javaのstreamを履修した方なら理解できると思いますが, Stream APIにおける各メソッドそのままの挙動をします.
Map(Operator, List)
右スロットで指定したListを左スロットで指定したOperatorに従って処理し結果を出力する関数です. 値を加工するのに用いますが, こちらは省略することも出来るので慣れれば余り使わないのではないかと思います.
また, ここで左スロットに指定するOperatorは出力と入力が単一でなければならず, これをPredicateと呼びます. (公式wikiでも同等の記述があります.)
Filter (Operator, List)
こちらは上記のmapと似たような関数で, 数値の加工の代わりに条件に合致した要素のみを残したListを返す関数です.
こちらも使用するOperatorはPredicateである必要があります.
Pipe(Operator, Operator)
左側のスロットの結果を右側のスロットのOperatorの入力へと渡します.
左側のOperatorを便宜上 left() として, 右も同様にright() とすると, 次のような挙動であると言えます:
right( left() )
上手く使うことで逐一mapを挟む必要が無くなるのでvalriable cardの節約になり後の修正が楽になります. 基本的には値の加工は連続して行うのでこれを使っていく必要が出てきます.
罠1: apply
満を持して今回の罠の登場です. これに2時間取られてフレンドに多分嫌われたのでこの記事を書いている訳ですが.
つかいかた
単純で, 導入にて触れたように条件式となるOperatorは加工する値と条件式(何かしら関数が必要とするもの)の入力を2つ必要としています.
これに対してapplyにてこのOperatorに対して第一引数へ値を渡す事が出来ます. ここで渡される先はあくまで第一引数です. 覚えておきましょう.
ここで, a -> b -> cでは読みづらいのでメソッド風に書くとこうなります.
NBT.nbtCompoundValueDouble(NBT, String)
ここで渡されるべきキーはStringであるはずですがapplyにてそのままStringを渡すと第一引数であるNBTへ代入されてしまいエラーとなります.
なんてこった.
当然第二引数に値を渡すなんて気の利いた関数は存在しません.
わァ…!
罠2: flip
こいつも俺に見つけられるまでの時間を稼いだので戦犯とします(理不尽).
どう使うのか
先の引数問題についての至極簡単な答が存在します. 引数の順を入れ替えれば良いのです. それだけ.
罠というよりは救世主ですが, どちらかといえば罠寄りです. なぜなら関数が読み辛ェので.
先のapply事故は一旦flipを挟むことでString -> Doubleという名前と合致しない意味不明の関数からNBT -> Doubleという素晴らしい値加工用の関数と変身する訳です.
こうしてIntegrated Dynamicsを完全攻略出来るわけです.
是非やってみましょう(苦しめ).