言語仕様 · Playground

Kairos 2 級教本 — 作文 / Writing Kairos (Grade 2 Textbook)

: v1(2026-08-02・言語 RC5 準拠・spec_head: 44493ad)。2 級のねらい=業務要件の文章から、スケジュール定義を 自分で書けるようになる(3 級=読解の上位)。正本は常に言語仕様—— 本書は作文の道筋を示すだけで、仕様を再定義しない。

本書の読み方: 2 級の理解は本文と章末演習で完結する。参照リンクは正本の確認用(仕様は 辞書として引く——実例から入るなら reference)。本文の 「動かして読む」の例はすべて実行検証済み# eval: が評価範囲・直後のブロックが実際の出力)。各例の下の「▶ Playground で開く」から、ブラウザでそのまま実行・改変できる(インストール不要・kairos-lang.org/playground)。 そして 2 級の作法をひとつ: 書いたら必ず動かして確かめる。作文の正誤は見た目でなく出力で 決まる——演習の判定基準が「同一出力(別解可)」なのはこのため。

第 1 章 要件文を分解する——「生成 → 窓 → 選択 → 変換」

作文の型は一つ。要件文の語を四つの役割に振り分けてから、パイプの順に置く。

毎月 25 日。ただしその日が土日または祝日なら、直前の営業日に繰り上げる。

動かして読む——組み上げた完成形。祝日データと営業日導出は前提側に置く:

# eval: 2026-07-01..2026-11-01
premise JP {
  calendar-system: Gregorian
  tz: "Asia/Tokyo"
  wkst: Mon
}

@JP
holidays2026 = [2026-01-01, 2026-01-12, 2026-02-11, 2026-02-23, 2026-03-20,
                2026-04-29, 2026-05-03, 2026-05-04, 2026-05-05, 2026-05-06,
                2026-07-20, 2026-08-11, 2026-09-21, 2026-09-22, 2026-09-23,
                2026-10-12, 2026-11-03, 2026-11-23] covering: 2026..2026
satSun = everyDay |> filter(d => weekday(d) == Sat or weekday(d) == Sun)
bizDay = everyDay \ (satSun | holidays2026)

everyDay |> within(month) |> nth(25) |> roll(Preceding, on: bizDay)
2026-07-24
2026-08-25
2026-09-25
2026-10-23
# 被覆サマリ
#   holidays2026 covering 2026-01-01..2026-12-31 残走路 61 日

▶ Playground で開く

7/25(土)と 10/25(日)だけが金曜へ動いた。要件文の「但し書き」は末尾の変換に落ちる—— この対応が崩れていないか、書いたら出力で確かめる。

第 2 章 「第 N」と「最終」——窓の中で選ぶ

「第 2 金曜」「最終金曜」のような要件は、選ぶ対象を先に絞ってから窓で数えるのが型。

everyDay |> filter(d => weekday(d) == Fri) |> within(month) |> nth(2)

金曜だけの列を作ってから、月窓の第 2 要素を取る。順序を逆にすると「各月 2 日のうち金曜の日」に 化ける(この罠は演習で)。「最終」は二通り書ける——within(month) |> last(窓の中の最後)と、 monthEnd |> roll(Preceding, on: 金曜列)(月末から手前へ寄せる)。同一出力で、読み下しの好みで 選んでよい。rollon: には名前を付けていないインラインの列も渡せる(匿名軸)。

動かして読む——最終金曜の roll 形:

# eval: 2026-08-01..2026-12-01
premise JP {
  calendar-system: Gregorian
  tz: "Asia/Tokyo"
  wkst: Mon
}

@JP
monthEnd |> roll(Preceding, on: (everyDay |> filter(d => weekday(d) == Fri)))
2026-08-28
2026-09-25
2026-10-30
2026-11-27

▶ Playground で開く

第 3 章 営業日と roll——寄せる向きは業務が決める

roll(Preceding) は手前へ、roll(Following) は先へ。どちらへ倒すかは文法でなく業務の意味が 決める——給料(支払う側の前倒し)は Preceding、請求の支払期日(受け取る側の期日)は Following が 商慣習の型。要件文の「繰り上げ/繰り下げ」の一語を読み落とすと、式は綺麗でも業務が壊れる。

動かして読む——同じ「毎月 25 日」を両向きに倒す。前提は第 1 章と同じ:

# eval: 2026-07-01..2026-11-01
premise JP {
  calendar-system: Gregorian
  tz: "Asia/Tokyo"
  wkst: Mon
}

@JP
holidays2026 = [2026-01-01, 2026-01-12, 2026-02-11, 2026-02-23, 2026-03-20,
                2026-04-29, 2026-05-03, 2026-05-04, 2026-05-05, 2026-05-06,
                2026-07-20, 2026-08-11, 2026-09-21, 2026-09-22, 2026-09-23,
                2026-10-12, 2026-11-03, 2026-11-23] covering: 2026..2026
satSun = everyDay |> filter(d => weekday(d) == Sat or weekday(d) == Sun)
bizDay = everyDay \ (satSun | holidays2026)

everyDay |> within(month) |> nth(25) |> roll(Preceding, on: bizDay)   # 式 1: 給料日(前倒し)

everyDay |> within(month) |> nth(25) |> roll(Following, on: bizDay)   # 式 2: 支払期日(後ろ倒し)
# 式 1(4 件)
2026-07-24
2026-08-25
2026-09-25
2026-10-23
# 式 2(4 件)
2026-07-27
2026-08-25
2026-09-25
2026-10-26
# 被覆サマリ
#   holidays2026 covering 2026-01-01..2026-12-31 残走路 61 日

▶ Playground で開く

平日の 25 日(8 月・9 月)は両者一致。土日に当たる月だけ、向きの差が日付の差になって現れる。

第 4 章 値式の filter——条件を数式で書く

曜日や序数の列挙で書けない条件は、点の座標を値に射影して数式で判定する。「五十日 (毎月 5・10・15・20・25・30 日)」は nth を 6 本並べるより、dayNo(d)(月内の日番号)の剰余が 早い:

動かして読む:

# eval: 2026-09-01..2026-10-01
premise JP {
  calendar-system: Gregorian
  tz: "Asia/Tokyo"
  wkst: Mon
}

@JP
everyDay |> filter(d => dayNo(d) mod 5 == 0)
2026-09-05
2026-09-10
2026-09-15
2026-09-20
2026-09-25
2026-09-30

▶ Playground で開く

31 日は 31 mod 5 == 1 なので自然に落ちる——列挙の代わりに条件の構造を式にするのが値式 filter の使いどころ。使える射影は dayNomonthNoyearNo・曜日ラベル weekday(d) など (reference の各ページに実例)。

第 5 章 結合子で規則を合成する

一本のパイプで書けない要件は、規則ごとに列を作って結合子で合成する。「第 1・第 3 月曜」は nth が序数を一つしか取らないので、二本の列ので書く:

動かして読む——束縛で部品に名前を付けると重複が消える:

# eval: 2026-09-01..2026-11-01
premise JP {
  calendar-system: Gregorian
  tz: "Asia/Tokyo"
  wkst: Mon
}

@JP
mondays = everyDay |> filter(d => weekday(d) == Mon)
(mondays |> within(month) |> nth(1)) | (mondays |> within(month) |> nth(3))
2026-09-07
2026-09-21
2026-10-05
2026-10-19

▶ Playground で開く

| は集合の和(同じ点は 1 点に正規化)・積 & は両方に現れる点・差 \ は除外。 「金曜かつ 13 日」のような独立二条件は積で、「営業日から休業日を除く」は差で—— 要件文の接続詞が結合子に対応する

巻末——2 級の到達確認

  1. 要件文を「生成→窓→選択→変換」に分解できる(第 1 章)
  2. 「第 N・最終」を絞り込み→窓の順で書ける(第 2 章)
  3. roll の向きを業務の意味から選べる(第 3 章)
  4. 列挙で書けない条件を値式 filter に落とせる(第 4 章)
  5. 複数規則を結合子で合成できる(第 5 章)

そして書いたら動かす。各章末の演習は「同一出力なら別解可」——自分の答えと模範解の出力を リファレンス実装で見比べるところまでが作文の練習。