scan — 時間軸に沿った状態の進化
scan
は、このライブラリで最も強力なプリミティブの一つです。これは、時間とともに進化する「状態」を持つタイムラインを構築するための、基本的なツールとなります。
畳み込みの3つの次元:構造と時間
Section titled “畳み込みの3つの次元:構造と時間”scan
のユニークな役割を理解するため、プログラミングにおける3種類の「畳み込み(fold)」を比較します。最初の2つは構造 (Structure) を扱い、3つ目のscan
は時間 (Time) という全く異なる次元を扱います。
fold
(構造の畳み込み):[1, 2, 3]
のような配列(静的なコレクション構造)を扱い、一つの最終的な値(例:6
)を算出します。foldTimelines
(構造の畳み込み):[Timeline<1>, Timeline<2>, Timeline<3>]
のようなタイムラインのリスト(動的なコレクション構造)を扱い、それらを一つの結果タイムラインに合成します。scan
(時間の畳み込み):1 -> 2 -> 3
のような単一のタイムライン(時間的なイベントストリーム)を扱い、イベントが発生するたびに途中経過の値を保持する新しいタイムライン(例:1 -> 3 -> 6
)を生成します。
これらの違いをまとめたのが、以下の比較表です。
特徴 | fold (構造) | foldTimelines (構造) | scan (時間) |
---|---|---|---|
目的 | 最終的な集計 | 構造的な合成 | 時間的な集約 |
入力 | 配列など | タイムラインのリスト | 1つのタイムライン |
処理 | 一度に全体 | 一度に全体 | イベントのたびに |
出力 | 1つの最終値 | 最終結果のタイムライン | 途中経過のタイムライン |
比喩 | 買い物かごの合計金額 🧾 | 複数の投票の最終集計 🗳️ | 銀行口座の残高推移 📈 |
fold
とfoldTimelines
は、共に入力となる「コレクション構造」を一つにまとめる点で非常によく似ています。一方でscan
は、単一のストリームの時間的な変化を追跡するための、全く異なる目的を持つツールであることが、この比較から明確になります。それは過去の履歴を記憶し、新しい入力に基づいて状態を更新していく、状態を持つタイムラインを構築するための核心的な操作なのです。
F#: scan: ('state -> 'input -> 'state) -> 'state -> Timeline<'input> -> Timeline<'state>
Section titled “F#: scan: ('state -> 'input -> 'state) -> 'state -> Timeline<'input> -> Timeline<'state>”Note: In F#, scan
is a standalone function.
TS: .scan<S>(accumulator: (acc: S, value: T) => S, seed: S): Timeline<S>
Section titled “TS: .scan<S>(accumulator: (acc: S, value: T) => S, seed: S): Timeline<S>”TypeScriptによるコード例
Section titled “TypeScriptによるコード例”scan
の動作を、流れてくる数値を合計していくカウンターで見てみましょう。
// 数値のタイムラインを作成const numberStream = Timeline<number>(0);
// scanを使って、流れてくる数値を合計していくconst runningTotal = numberStream.scan( (sum, currentValue) => sum + currentValue, // accumulator: 現在の合計値に新しい値を加算 0 // seed: 合計値の初期値);
// runningTotalは常に最新の合計値を保持するconsole.log(runningTotal.at(Now)); // 0
numberStream.define(Now, 5);console.log(runningTotal.at(Now)); // 5 (0 + 5)
numberStream.define(Now, 10);console.log(runningTotal.at(Now)); // 15 (5 + 10)
numberStream.define(Now, -3);console.log(runningTotal.at(Now)); // 12 (15 - 3)
Canvasデモ (Placeholder)
Section titled “Canvasデモ (Placeholder)”入力タイムラインに数値が流れるたびに、scan
によって構築された状態タイムライン(合計値)がリアルタイムに更新されていく様子を視覚化するデモ。