segmentBy — 区間列型窓(マーカーで切る)
分類: 窓(本体層 core) / シグネチャ: segmentBy(m, edges:, empties:) : Stream -> Stream(interval) / 名は確定(spec §5.4)
意味
任意のストリーム m をマーカーとし、隣り合うマーカーの半開区間 [mᵢ, mᵢ₊₁) を窓とする。
決算期・月相(朔で切る太陰太陽暦)・週(wkst ラベル日で切る)など、「点の列が境界を与える」窓は
すべてこれで立つ。
パーティション型と違い網羅は保証されないので、隙間の意味を明示する二つの引数が宣言必須 (I5・省略は静的エラー)。データ欠損で発報が静かに消える事故(ADR-15「事故の空」)を構文で防ぐ。
引数
| 引数 | 値 | 意味 |
|---|---|---|
m |
ストリーム式 | マーカー(区間の境界点) |
edges: |
drop / clip / error |
最初のマーカー前・最後のマーカー後の点の扱い(捨てる/部分窓を作る/エラー) |
empties: |
keep / drop / error |
マーカー間の要素ゼロ窓の扱い(正当な空として保持/捨てる/エラー) |
labels: |
リスト(リテラル/リスト束縛名)または周期形 cycle リスト anchor: 実日(ADR-47・後述) |
窓列への並行ラベル列(ADR-39)。読みは束縛名射影 束縛名(d)。組合せの締めは「前提条件と締め」(後述)——edges: clip・empties: drop・label: とは組めない |
label: |
ラムダ (p => 式) |
窓の計算ラベル(ADR-34。labels: に乗らない添字式・条件つき計算用) |
例
朔(新月)で切る旧暦月——各月の第 1 日(朔日)を採る。旧正月 2026-02-17 が現れる:
# eval: 2026-01-01..2026-05-01
@JP
newMoons = [2026-01-19T04:52, 2026-02-17T21:01, 2026-03-19T10:23, 2026-04-17T20:52]
lunarStart = newMoons |> snapTo(day)
everyDay |> segmentBy(lunarStart, edges: drop, empties: drop) |> first
#=> 2026-01-19 2026-02-17 2026-03-19
#~> 範囲外 2026-01-01..2026-01-19(newMoons covering 2026-01-19T04:52..2026-04-17T20:52)
#~> 範囲外 2026-04-17..2026-05-01(newMoons covering 2026-01-19T04:52..2026-04-17T20:52)
edges: drop なので最後のマーカー 4/17 以降は窓にならない(データの端で黙って続けない)。
labels:——窓列への並行ラベル列(ADR-39)
データのラベル列を窓列に結ぶ。読みは束縛名射影——束縛名(d) が点 d の属する窓のラベルを返す
(名前(d) ≡ labels[窓列序数]・窓列序数は実効被覆域内の先頭マーカー起点の窓が 0)。同長性検査が
評価時に走る: リスト長 == 窓数(窓数は覆域基準=マーカー数。評価範囲・実体化範囲に依存しない)——
マーカーとラベルの対更新忘れが静的エラーで割れる(F62 の器):
# eval: 2026-01-01..2026-07-01
@JP
newMoons = [2026-01-19T04:52, 2026-02-17T21:01, 2026-03-19T10:23, 2026-04-17T20:52]
covering: 2026-01-19..2026-04-30
lunarMonth = everyDay |> segmentBy((newMoons |> snapTo(day)), edges: drop, empties: error,
labels: [12, 1, 2, 3])
lunarMonth |> first |> filter(d => lunarMonth(d) == 1)
#=> 2026-02-17
#~> 範囲外 2026-01-01..2026-01-19(newMoons covering 2026-01-19..2026-04-30)
#~> 範囲外 2026-05-01..2026-07-01(newMoons covering 2026-01-19..2026-04-30)
前提条件と締め(すべて静的エラー・ADR-39 判断 4): edges: clip とは組めない(擬似窓が序数を
ずらす)・empties: drop とは組めない(空窓の除去が序数を詰める)・label: ラムダと同居できない
(ラベル源の二重化)・規則マーカー(week 型の無限列)には付かない(周期ラベルは
cycle・計算番号は ordinalIn か label:)・合成マーカー(t1 | t2)は
実効被覆域が割れて窓数が確定しないので、束縛後置の被覆主張(covering:)で確定してから。
空窓(empties: keep)のラベルの読み口は区間所属——窓区間内の任意の点、実用上はマーカー点
そのものから読める(欠ティティの番号が立つ形)。複数の並行列(番号と名前)は同じマーカーで
別の窓束縛を立てるのが正準(検査が二重に効く。../stdlib/kyureki.md §1)。
labels: cycle——窓列への周期ラベル(ADR-47)
「窓列=暦の単位・ラベル=固定周期」の形(節切り月の十二支・月家九星・月星座の 12 宮)は
周期形 labels: cycle リスト anchor: 実日 で書く。意味論は窓束縛への cycle と
同一——「anchor の属する窓が先頭ラベル」(list[(窓列序数 − anchor 窓の序数) mod N]・負も
法で正規化)。同長性検査は課さない——covering が複数年に伸びてマーカーが増えても、anchor は
そのままで式は一字も変わらない(external 供給〈ADR-46〉との相性がこの形の狙い)。
# eval: 2026-02-03..2026-02-06
@JP
setsu = [2026-01-05, 2026-02-04, 2026-03-05, 2026-04-04] covering: 2026-01-05..2026-04-04
sekkiMonth = everyDay |> segmentBy(setsu, edges: drop, empties: error,
labels: cycle [寅, 卯, 辰, 巳, 午, 未, 申, 酉, 戌, 亥, 子, 丑]
anchor: 2026-02-04)
everyDay |> filter(d => sekkiMonth(d) == 寅)
#=> 2026-02-04 2026-02-05
- anchor(立春 2/4)の窓が寅——その前の窓(小寒 1/5〜)は負の法正規化で丑になる。
anchor:は形の一部(必須・カンマで切らない)。マーカー点との一致は不要——属する窓で決まる。 頭側・範囲外に落ちる anchor は明示エラー(覆域の年次更新で anchor の窓が消えたら、リスト周期 N 窓分先の対応実日へ進めれば全ラベル不変)。- リストは逆順にすれば逆行の周期(月家九星)も書ける。リスト束縛名も可(静的形と対称)。
- 守るのは位相の宣言のみ——マーカーの中途挿入・欠落や、非周期の列(旧暦月番号——閏月は
前月番号の繰り返し)への誤用は、エラーも註釈も出ずにラベルが黙って回る(照合相手のリストが
ないため機械検出は原理的に不可能)。周期でないデータラベルは静的
labels:で(同長性検査が 対更新忘れを守る)。中身の照合は doctest・coincidesの分担。
label:(ADR-34)
括弧内の named-arg segmentBy(m, edges:, empties:, label: (p => 式)) で各窓に計算ラベルを貼れる
(p=窓の先頭点・射影時の遅延評価)。データ列を貼るだけなら labels: が正準(ADR-39・ADR-30 改訂)で、
label: は添字式・条件を含む計算用(../stdlib/kyureki.md §7 (5))。
落とし穴
edges:/empties:の省略は静的エラー。「よく使う組」を糖衣に畳む余地はある(ADR-23)が、core では 常に明示する。- 窓が粗い単位列を細かいマーカーで切るときの所属は代表点(窓要素なら先頭点)で決まる(spec §5.2)。
segmentBy製でも、切れ目が周期的で網羅・無重複が示せる窓は I5 検査でパーティション型と認定され、withinに使える——標準のweekがその例(day |> segmentBy(weekStart, edges: clip, empties: error)。 stdlib/gregorian.md §4.5)。- anchor の粒度がマーカーより粗いと意図の前窓に付き得る——instant 級マーカー(
snapTo(day)を通していない朔・節気の瞬間)の窓列に日付リテラルの anchor を書くと、日の先頭 00:00 がマーカー 時刻より前=前の窓に区間所属する(エラーにならず位相が 1 窓ずれる)。実用形はマーカーと 同じ snap を経た anchor、または時刻付きリテラル(ADR-47)。 - 頭側(覆域始端〜最初のマーカー)は窓列の範囲外(ADR-37 改訂 3)——
edges: drop/errorの 窓列で覆域始端より最初のマーカーが後ろにある構成(filter 派生マーカーの典型: 12 点のテーブルを filter で 4 点に絞ると覆域はそのまま・最初のマーカーだけ後退する)では、頭側の点への labels 射影・coincidesは範囲外註釈で応える(filter 正準形は頭側の点を落として註釈)。頭側を覆域からも 外したいなら派生束縛への縮小 covering 主張(starts = setsu |> filter(…) covering: 2026-02-04..)。 labels:付きの窓束縛は窓インスタンス参照(値引数適用・ADR-42)が立つ——sekkiW("立春")は 立春節の期間の全日(2/4〜2/18 級)で、テーブル射影のsekki |> filter(s => sekki(s) == 立春)(立春の点)とは別物。点が欲しいならテーブル filter・期間の日々が欲しいなら窓インスタンス参照。 番号ラベルは一意キーでない点にも注意(lunarMonth(6)は閏六月〈前月番号の繰り返し〉を含む ——全マッチ和。名前ラベルkyuMonth("六月")なら閏六月は別)。
関連
within・snapTo(マーカーの粒度合わせ)・cycle(周期ラベル)・
テーブルリテラル(マーカーのデータ持ち込み)・ADR-07/08/15・I5。