ASTERIAでランダムで「ずん」と「どこ」を出現させ,
「ずん」「ずん」「ずん」「ずん」「どこ」と来たら「きよし」出力させて終了する.
全体像
解説① 前提条件について
「ずん」とか「どこ」をどっかで記録する必要がるのですが、他の言語を見ると配列を使っている方が大半だと思うのですが,
①ループのなかでMapperコンポーネントのParametaListを使うと初期化されるんですね.
ということで, 却下(初期化されない方法をご存知の方はそれをご教示お願いします.)
②StreamPutコンポーネントで記録する方法ですが, こちらは"代入"しかなく,追加(Linuxなら追記)機能がない.
ということで, 自分としてはやりたくないのですが,
追加処理のある "ファイル"に記憶させます.
解説② 再帰処理
「ずん」「ずん」「ずん」「ずん」「どこ」と並んだ終了となり, その並びになるまで処理を繰り返す.簡単に言えば, 再帰処理ですね.
再帰処理の条件は
①無限ループである
②無限ループを抜ける終了条件がある(=これを"基底部"というそうです)
①無限ループについて
ASTERIAには無限ループが存在しないので(するかもしれないが私は知らない),
LoopStartコンポーネントを999回として, 事実上無限ループになるよう偽装する.
②基底部について
BranchStartコンポーネントは,
条件式がTRUEならば→のフローへ
条件式がFALSEならば↓フローへ行きます.
TRUEのときに, 無限ループから抜けれるように, 最後にBreakコンポーネントを設置.
ちなみにですが, ASTERIAには自己再帰(フローの中に,自分のフローを追加する)が設定できないようです.(フローだけでなく, 関数でもできません.)
無理矢理行うと以下のエラーが出力されます.
解説③「ずん」or「どこ」をランダム出力
ランダムを出すのは基本的にRandコンポーネントでしょうか.(私は実務で使ったことがないです)
ここでは深く意識する必要はないとか思いますが, ランダムを使用するときは何分布かを意識する必要があります.
ヘルプ を見ても, 特に書いてないですね.
最終的に 0 or 1 を出力させたいので,
一様分布でやるのが基本ですが, もしかしたら正規分布かも知れません.
ランダムのほかにも出すやり方として,
システムIDや実行時のミリ秒をmodして偶数か奇数かで判定するやり方する方もいるかもしれませんね.(もしかしたらRandの内部処理はこちらかも知れません.)
解説④ 「ずん」「ずん」「ずん」「ずん」「どこ」の判定
最後の5つだけがどう出力されたかが判定条件ですので, 他は不要です.
RecordFilterコンポーネントは
Linuxでいう tail -n 5 をしているイメージです.
読み込み開始行を ${stream.RecordCount}-4 だとうまく動かなかったので, その手前でMapperで求めてるだけです.
解説⑤ INNER JOIN はJOINだけの意味ではない
RecordTransposeコンポーネントで縦横転置して,Velocityコンポーネントで直接入力した正しい値と合致するか判定して,
判定が正しい(=すなわち出力レコードが1つか)を判定しています。
普通は
RecordFilterコンポーネントの条件式で
$record.field1 ="ずん" && $record.field2 ="ずん" && $record.field3 ="ずん" && $record.field4 ="ずん" && $record.field5 ="どこ"
と書いてもいいのですが, 私なら絶対にINNER JOINを使います.
結果を見てみましょう
こっからは余談.
このフローを100回まわして, 平均何回で出力されるのか知りたいくないですか?
平均値:32.25
MAX:167回
MIN:5回
だそうです. 一応参考までに.
戻り値
サブフローはBreakコンポーネントまで行くと,
最後はEnd(Response)コンポーネントに行くようです.
戻り値にレコードのループ回数を入れているのですが,
親フローからモドリッチ(←言いたいだけ)をどうやってうけとるのでしょうか?(私はストリームからとりました)
ここ難しいです.
あくまで一例です.
他にも色々な方法が存在すると思いますので,
私ならもっとベストプラクティスがある!との方は是非Qiitaにお願いします!