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 日。ただしその日が土日または祝日なら、直前の営業日に繰り上げる。
- 「毎月」——窓。月で区切る:
within(month) - 「25 日」——選択。窓の中の第 25 日:
nth(25) - 「ただし〜繰り上げる」——変換。無効な日を有効な日へ寄せる:
roll(Preceding, on: bizDay) - 素材はいつも生成子から:
everyDay
動かして読む——組み上げた完成形。祝日データと営業日導出は前提側に置く:
# 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 日
7/25(土)と 10/25(日)だけが金曜へ動いた。要件文の「但し書き」は末尾の変換に落ちる—— この対応が崩れていないか、書いたら出力で確かめる。
- 参照(正本の確認用): 仕様 §7.4(給料日)
- 演習: L2-015 支払期日(翌営業日)——同じ要件文の 「繰り上げ」を「繰り下げ」に変えると、式はどこが変わるか
第 2 章 「第 N」と「最終」——窓の中で選ぶ
「第 2 金曜」「最終金曜」のような要件は、選ぶ対象を先に絞ってから窓で数えるのが型。
everyDay |> filter(d => weekday(d) == Fri) |> within(month) |> nth(2)
金曜だけの列を作ってから、月窓の第 2 要素を取る。順序を逆にすると「各月 2 日のうち金曜の日」に
化ける(この罠は演習で)。「最終」は二通り書ける——within(month) |> last(窓の中の最後)と、
monthEnd |> roll(Preceding, on: 金曜列)(月末から手前へ寄せる)。同一出力で、読み下しの好みで
選んでよい。roll の on: には名前を付けていないインラインの列も渡せる(匿名軸)。
動かして読む——最終金曜の 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
- まず読む: reference/nth・reference/roll(実例つき)
- 正本の確認用: 仕様 §4.3(選択子)
- 演習: L2-003 毎月の第 2 金曜・L2-009 毎月の最終金曜
第 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 日
平日の 25 日(8 月・9 月)は両者一致。土日に当たる月だけ、向きの差が日付の差になって現れる。
- まず読む: reference/roll・reference/nonWorking(営業日の導出)
- 正本の確認用: 仕様 §4.4(点変換)
- 演習: L2-014 毎月の最終営業日
第 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
31 日は 31 mod 5 == 1 なので自然に落ちる——列挙の代わりに条件の構造を式にするのが値式
filter の使いどころ。使える射影は dayNo/monthNo/yearNo・曜日ラベル weekday(d) など
(reference の各ページに実例)。
- まず読む: reference/filter(実例つき)
- 正本の確認用: 仕様 §4.9(窓→値の射影)
- 演習: L2-011 五十日
第 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
和 | は集合の和(同じ点は 1 点に正規化)・積 & は両方に現れる点・差 \ は除外。
「金曜かつ 13 日」のような独立二条件は積で、「営業日から休業日を除く」は差で——
要件文の接続詞が結合子に対応する。
- まず読む: reference/combinators(実例つき)
- 正本の確認用: 仕様 §4.5(結合子)
- 演習: L2-013 第 1・第 3 月曜
巻末——2 級の到達確認
- 要件文を「生成→窓→選択→変換」に分解できる(第 1 章)
- 「第 N・最終」を絞り込み→窓の順で書ける(第 2 章)
- roll の向きを業務の意味から選べる(第 3 章)
- 列挙で書けない条件を値式 filter に落とせる(第 4 章)
- 複数規則を結合子で合成できる(第 5 章)
そして書いたら動かす。各章末の演習は「同一出力なら別解可」——自分の答えと模範解の出力を リファレンス実装で見比べるところまでが作文の練習。