日本語 · English

labelOrdinal — 宣言値域の中でラベルが第何番目か

分類: 射影(値式・本体層 core) / シグネチャ: labelOrdinal(B, x) : ラベル値 -> 数値(点形 labelOrdinal(B, d) : 点 -> 数値) / 名は確定(ADR-54・2026-10-19・spec §5.4) / 1.1 の追加拡張

意味

束縛 B が宣言した値域(ラベルの列挙)の中で、ラベル値 x が第何番目かを返す(1 起点・宣言順)。 labelOrdinal(weekday, Sun) は 7、labelOrdinal(saku, m3) は 3。ラベルは文字列値で、識別子形と文字列形は 同じ値(m3 と "m3"。spec §5.5)。

値域になるのは宣言リスト 3 形だけ:

値域の源 書き方 読む例
external の labels: saku = external(kind: dates, labels: [m1, …, m12]) labelOrdinal(saku, m3) → 3
窓束縛 cycle weekday = day cycle [Mon, …, Sun] anchor: … labelOrdinal(weekday, Sun) → 7
segmentBy の labels: cycle sekkiMonth = … labels: cycle [寅, 卯, …] anchor: … labelOrdinal(sekkiMonth, 卯) → 2

意味論は定義的等式 1 行——labelOrdinal(B, v) ≡ v == E₁ ? 1 : … : v == Eₙ ? n : ⊥。右辺は 1.0 の値式だけで 書ける三項のネスト(旧正準形)の畳み込みで、違いは既定枝が ⊥=明示エラー「値域の外」になること。

値域が数値や論理値のリスト(labels: cycle [10, 20, 30])でも同じく位置を返す——値域はリストで、型で特別扱いしない (ADR-54 判断 5)。

点形 labelOrdinal(B, d) は labelOrdinal(B, B(d)) の略——点 d を先に B(d) の束縛名射影で ラベルにし、そのラベルの序数を返す。範囲外の註釈(spec §4.10)も tz 名検査(ADR-40)も B(d) のものが そのまま効き、本語自身は註釈を生まない。

例

曜日番号——weekday の cycle のリスト順(Mon=1 … Sun=7)。wkst に依らない(wkst: Sun の下でも 日曜が 7。週の中の第何日は ordinalIn(day, week, d) で、こちらは wkst: Sun なら土曜が 7):

# eval: 2026-01-01..2026-01-20
premise US { calendar-system: Gregorian; tz: "Asia/Tokyo"; wkst: Sun }
@US
everyDay |> filter(d => labelOrdinal(weekday, d) == 7)
#=> 2026-01-04 2026-01-11 2026-01-18

labels: cycle の値域——節切り月(立春の窓が寅)。卯月=宣言順の 2 番目:

# eval: 2026-02-03..2026-03-07
@JP
setsu = [2026-01-05, 2026-02-04, 2026-03-05, 2026-04-05] covering: 2026-01-05..2026-04-05
sekkiMonth = everyDay |> segmentBy(setsu, edges: drop, empties: error,
                                   labels: cycle [寅, 卯, 辰, 巳, 午, 未, 申, 酉, 戌, 亥, 子, 丑]
                                   anchor: 2026-02-04)
everyDay |> filter(d => labelOrdinal(sekkiMonth, d) == 2)
#=> 2026-03-05 2026-03-06

external の値域——六曜(大安)。朔のデータは旧暦月名のラベル(m1〜m12)と一緒に届く (external・# resolve: 行は doctest の解決子固定材)。月番号は labelOrdinal(saku, …) で 値域から読み、六曜は (月番号 + 旧暦日) mod 6(0 が大安。stdlib/kyureki.md §5):

# eval: 2026-02-17..2026-03-19
# resolve: saku = dates 2026-01-19 2026-02-17 2026-03-19 2026-04-17 2026-05-17 covering: 2026-01-01..2026-05-31 asof: 2026-09-03 labels: m12 m1 m2 m3 m4
premise L { calendar-system: Gregorian; tz: "Asia/Tokyo"; wkst: Mon; source: "moon/saku"
  saku  = external(kind: dates, labels: [m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12])
  lunar = day |> segmentBy(saku, edges: drop, empties: keep, label: (p => saku(p)))
  rokuyoNo = d => (labelOrdinal(saku, lunar(d)) + ordinalIn(day, lunar, d)) mod 6
}
@L
everyDay |> filter(d => rokuyoNo(d) == 0)
#=> 2026-02-21 2026-02-27 2026-03-05 2026-03-11 2026-03-17

lunar(d) は label: ラムダの計算ラベル(値域を持たない)なので、序数は値域を持つ側 saku から読む—— labelOrdinal(saku, lunar(d))。1.0 の書き方(三項 12 段の monthLabelNo)との違いは segmentBy の「ラベルを数値として使う」。

落とし穴

関連

ordinalIn・epochOrdinal(序数の一族)・cycle・ segmentBy(labels: cycle・1.0 互換の三項形)・external(labels: 値域)・ spec §4.9・ADR-54。