標準ライブラリ (stdlib)
本書 (std/) は 標準ライブラリモジュール を定義する。標準ライブラリは prelude (../prelude.md) と異なり root に常在しない。import x := "std:<name>" で明示的に取得する (解決規則は ../language-spec.md §13.4)。言語の意味論は language-spec.md を参照。
prelude が「stdio (print / input)・型メソッド・制御構造・非同期 (fork / sleep / now) といった常在的な核」を担うのに対し、標準ライブラリは 常在させるほど中核ではない機能を import で取得する領域を担う。その内容は外部リソースに限らず、名前で指す外部リソース (ファイル・端末・将来のネットワーク等) へのアクセスと、外部に触れない純粋な値・計算ユーティリティ (パス操作・構造デルタ・JSON 直列化等) の双方を含む。import を要することで root 名前空間を最小に保ち、加えて 外部リソースに触れるモジュールについては その import 自体が能力宣言となり、どのコードがどの能力を使うかが静的に追える (capability の可視化)。
各モジュールは std/ 配下に 1 ファイルずつ定義する。各モジュール文書中の裸の §N は その文書自身の節を指し、他文書の節は language-spec.md §X のように明示する。本書で定義する識別子は 2 語以上の場合 snake_case で命名する (prelude.md と同じ規約。例: read_bytes)。
モジュール一覧
| モジュール | 取得 | 内容 | 文書 |
|---|---|---|---|
std:fs |
import fs := "std:fs" |
ファイルシステム (read / read_bytes / write / open / File ほか) |
fs.md |
std:path |
import path := "std:path" |
パス文字列操作 (join / dir / base / ext) |
path.md |
std:term |
import term := "std:term" |
端末制御 (raw_mode / read_key / size) |
term.md |
std:term/event |
import event := "std:term/event" |
端末入力イベントのデコード (next_event / decode / mouse_on) |
term/event.md |
std:term/screen |
import screen := "std:term/screen" |
端末出力 ANSI 制御 (enter_alt / move / fg / 色定数) |
term/screen.md |
std:json |
import json := "std:json" |
JSON 直列化 (parse / stringify) |
json.md |
std:time |
import time := "std:time" |
日時 (now / of / Instant / Duration、UTC 固定) |
time.md |
std:http |
import http := "std:http" |
HTTP 共通型 (Request / Response / Handler) |
http.md |
std:http/client |
import client := "std:http/client" |
HTTP クライアント (get / post / request ほか) |
http/client.md |
std:http/server |
import server := "std:http/server" |
HTTP サーバー (serve) |
http/server.md |
std:math |
import math := "std:math" |
数学関数 (sqrt / pow / min / max / 三角関数 ほか) |
math.md |
std:decimal |
import decimal := "std:decimal" |
10 進小数 (of / parse → add / sub / mul / div / round・Decimal) |
decimal.md |
std:random |
import random := "std:random" |
擬似乱数 (seed / new → int / float / pick / shuffle ほか) |
random.md |
std:env |
import env := "std:env" |
環境変数と起動引数の読み取り (get → Option / get_or / args) |
env.md |
std:cli |
import cli := "std:cli" |
起動引数の解析 (option / flag で宣言 → parse → get / get_or / has。純粋・Spec / Parsed) |
cli.md |
std:map |
import map := "std:map" |
キー昇順の SortedMap・挿入順の InsertionMap (== キー同一性)・可変 scratch ハンドル ScratchMap (frozen で InsertionMap に確定) |
map.md |
std:set |
import set := "std:set" |
順序付き集合 (union / intersect / difference・OrderedSet) |
set.md |
std:array |
import array := "std:array" |
可変 scratch 配列 (get / set で O(1) 添字更新・frozen で List 確定・Array) |
array.md |
std:process |
import process := "std:process" |
サブプロセス実行 (run / exec / run_opts) |
process.md |
std:regex |
import regex := "std:regex" |
正規表現 (compile → test / find / captures / replace ほか。RE2 構文・線形時間) |
regex.md |
std:bits |
import bits := "std:bits" |
ビット演算 (and / or / xor / not / shift_left / shift_right) |
bits.md |
std:crypto |
import crypto := "std:crypto" |
暗号ハッシュ (sha1 / sha256 / md5)・HMAC (hmac_sha256)・定数時間比較 (constant_time_equal) |
crypto.md |
std:crypto/random |
import crand := "std:crypto/random" |
暗号用乱数 (bytes — ホストのエントロピー源。wasm では n > 0 なら Err) |
crypto/random.md |
std:net |
import net := "std:net" |
TCP クライアント (connect / connect_tls・Conn) |
net.md |
std:db |
— (契約のみ・import 不可) | RDB ドライバー横断契約 (プレースホルダー / 行と値の写像 / エラー kind / トランザクション) | db.md |
std:db/sqlite |
import sqlite := "std:db/sqlite" |
SQLite (open → query / exec / transaction・Db) |
db/sqlite.md |
std:hikari |
import hikari := "std:hikari" |
Hikari ソースの解析 (highlight — 意味分類スパンを返す) |
hikari.md |
std:hikari/doc |
import doc := "std:hikari/doc" |
言語リファレンスのメタデータ (entries / generated_notice) |
hikari/doc.md |
std:hikari/repl |
import repl := "std:hikari/repl" |
対話評価セッション (session → eval / check・needs_more・Session) |
hikari/repl.md |
std:assert |
import assert := "std:assert" |
アサーション (equal / not_equal / ok / length / empty / fail。失敗で panic) |
assert.md |
std:test |
import test := "std:test" |
テストの構築と実行 (test / suite / run。collect-then-run) |
test.md |
std:parallel |
import { map } := "std:parallel" |
不変データの並列変換 (map — 結果順は逐次同一・mapper は独立契約) |
parallel.md |
未知の std:<name> を import した場合は実行前の静的検査で弾かれる (static-analysis.md §1)。
引数は省略できない
std のメンバーは末尾 optional を持たない。 宣言したスロットはすべて書く — 自動に任せる値がある口(std:parallel の chunks・std:json の indent・std:term の read_key のタイムアウト)でも、その既定にあたる値(多くは 0)を明示する。
理由は言語の規則にある。../language-spec.md §3.6 は既定値スロットも未束縛スロットとして数えると定めるので、末尾を省いた呼びは部分適用になる。std の組込だけが既定値を補完すると、同じ綴りが「std なら完全適用・ユーザー定義なら部分適用」と読める状態になり、型検査がどちらに解いても片方が嘘になる。規則を曲げるより引数を書く方を採る。
全値が持つ copy(../language-spec.md §9.5)はこの規則の外である — x.copy! は overlay を取らない綴りとして言語が定めており、std のメンバーではない。
モジュールの効果
各モジュールが起こす効果 (../language-spec.md §17.9) を一覧する。線はモジュール単位ではなく能力単位で引く — 同じモジュールの中に効果を持つ口と純粋な口が混在してよく、下表は「そのモジュールが持ちうる効果の上限」を示す。個々のメンバーの効果は各書のメンバー表が定める。
| 効果 | モジュール |
|---|---|
Fs |
std:fs・std:db/sqlite |
Net |
std:net・std:http/client・std:http/server |
Io |
std:term・std:term/event |
Proc |
std:process・std:env |
Time |
std:time (現在時刻を読む口のみ) |
Rand |
std:random の new・std:crypto/random の bytes |
Mut |
std:array の Array・std:map の ScratchMap・std:random の seed とジェネレーター・std:net の Conn (set_timeout のみ) |
| 全効果 | std:hikari/repl の eval (下記) |
| 効果なし | std:path・std:json・std:math・std:decimal・std:set・std:bits・std:crypto・std:regex・std:term/screen・std:hikari・std:hikari/doc・std:assert・std:cli・std:test・std:parallel・std:http (型のみ)・std:db (契約のみ)・std:time の暦算術 |
std:term/screen が効果を持たないのは、ANSI 制御を文字列として組み立てるだけで自分では書き出さないためである。書き出すのは print (prelude) であり、そこで Io が付く。
std:random の seed(n) は同じ n に同じ列を生む決定的な口なので Rand ではなく、ジェネレーターの内部状態が前進する分の Mut だけを持つ。Rand を持つのは実行ごとに違う種を取る new() である。
std:crypto/random の bytes はホストのエントロピー源を読むので Rand を持つ。Fs ではない — 源はプラットフォームごとの系統呼び出しであって、名前で指すファイルではないためである (crypto/random.md §3)。std:crypto の側は純粋のままで、効果を 1 つも持たない。
std:net の set_timeout(ms) は接続へネットワーク越しに何かを送るわけではないので Net ではなく、ハンドルが持つ期限を書き換える分の Mut だけを持つ。書き換えは以降の read / write の挙動を変えるので呼び出し元から観測でき、フレーム外の可変状態への書き込みにあたる (../language-spec.md §17.9 の「Mut の判定」)。
std:array の Array と std:map の ScratchMap への書き込みは Mut だが、arr.build のように借用を貸し出して確定する bracket の内側では吸収されて外へ出ない (../language-spec.md §17.9 の「スコープ吸収」)。したがってこれらを内部で使うだけの関数は効果を持たない。
std:hikari/repl の eval は全効果を持つ。 評価する Hikari ソースは実行時にしか分からず、そのソースが何を呼ぶかを静的に絞れないためである。効果を持つ口としては唯一「上限を静的に狭められない」ものであり、eval を呼ぶコードは効果の観点で純粋になれない。check と needs_more は解析のみで評価しないため効果を持たない。
ブロックを受け取るモジュール関数・メソッドは、そのブロックパラメーターを EffectConduit で宣言する。渡したブロックの効果が呼び出し元へ透過するので、純粋なブロックを渡せば呼び出しも純粋である。線は「ブロックを起動するか」で引く (../prelude.md §17.4 と同じ規則)。
| モジュール | メンバー |
|---|---|
std:parallel |
map / filter / fold |
std:test |
test / suite |
std:array |
build / collect・Array の update |
std:map |
build・ScratchMap の update・各 map の each / map / filter / fold |
std:set |
各 set の each / map / filter / fold |
std:db/sqlite |
transaction |
std:term |
raw_mode |
std:term/event |
decode (バイトを読む 2 つの関数を受け取って呼ぶ) |
std:http/server |
serve (要求ごとに Handler を呼ぶ) |
std 名は原則フラット 1 語。密接に関連する能力群は <family>/<part> の 1 段階層で表す (例: http/client / http/server)。この階層はモジュール名 (文字列) の一部であり、ファイルシステムのようなネスト構造や import の解決規則自体を導入するものではない。