roll — 無効点を有効点へ寄せる
分類: 点変換(本体層 core) / シグネチャ: roll(conv, on: P) : Stream -> Stream / 名は確定(spec §5.4)
意味
各点が軸 P 上の有効点でなければ、規約 conv に従って有効点へ寄せる。有効点は動かない。
「休日なら前営業日」「日曜の祝日は翌平日に振り替え」の核となる演算子。
ロール規約は軸非依存(ADR-13)——営業日にも DST にも同じ体系が乗る。規約と軸は必須引数 (I3: 無効・不在に着地し得る演算子は解決を必須引数に取り、既定で黙って選ばない)。
| 規約 | 意味 |
|---|---|
Following |
次の有効点へ |
Preceding |
前の有効点へ |
Modified |
上位窓を引数に取り、その窓内に留めて寄せる(月をまたぐなら反対側へ。ADR-14) |
on: には軸名のほか導出ストリームをそのまま渡せる(ADR-26)——これが振替休日の鍵になる。
例
給料日: 毎月 25 日、休日なら前営業日(2026-01-25 は日曜 → 1/23 金曜):
# eval: 2026-01-01..2026-02-01
@JP
everyDay |> within(month) |> nth(25) |> roll(Preceding, on: bizDay)
#=> 2026-01-23
#~> 範囲外 2026-01-01..2026-01-02(holidays2026 covering 2026-01-01..2026-12-31, asof 2026-01-05)
振替休日: 日曜の祝日を「祝日でない日」という導出軸で前方に寄せる。連休(5/4・5/5 も祝日)を 自動で飛び越えて 5/6 に着地する:
# eval: 2026-05-01..2026-06-01
@JP
statutory = [2026-05-03, 2026-05-04, 2026-05-05] covering: 2026..2026
nonHoliday = everyDay \ statutory
statutory |> filter(d => weekday(d) == Sun) |> roll(Following, on: nonHoliday)
#=> 2026-05-06
匿名軸(インライン・ストリーム式)も受ける——named-arg は stream-expr を取り(spec §5.6)、 導出ストリームは軸と同じ型(F7・ADR-26)。名前を付けずに「月内最終金曜」が書ける (実装系還流第 3 便の「良い発見」を保証として明文化):
# eval: 2026-01-01..2026-03-01
@JP
month |> last |> roll(Preceding, on: (everyDay |> filter(d => weekday(d) == Fri)))
#=> 2026-01-30 2026-02-27
落とし穴
rollは点を間引かない(各点 → 1 点)。間引くのはfilter。- 複数の点が同じ有効点に寄ると重複は畳まれる(ストリームは点の集合)。
- 軸を前文に畳んでいれば
on:を省略できる(@JP axis: bizDayの下でroll(Preceding)。spec §3.3)。 ただしロール規約そのものは常に明示する。 - 入力と軸は整列の一致を要する(ADR-36・spec §4.5)——時刻付きの点列を日次の軸に寄せる形は
静的エラー(先に
snapTo(day)で明示的に揃える)。on:にはカレンダー実体名の直指(on: TSE)も 立てられる(標準導出への読み替え・ADR-35)。 - 短い軸に注意——
on:に窓インスタンス参照(on: year(2020)級・ADR-42)や covering の短い テーブルを渡すと、軸が有界になり着地なしの点は註釈なしで消える(規則由来=覆域完結の側は 「落として註釈」にならない・ADR-37 判断 4 の roll 行)。特定期間に絞るなら roll の後で&が安全。