Skip to content

標準ライブラリ

Strand の標準ライブラリは「最小完備」を目標に設計されている。同じ目的の関数を複数提供しない(AI の選択を曖昧にしないため)。


2.1 ビルトイン型

2.1.1 プリミティブ

表現リテラル例
TextUTF-8 文字列"hello"
Int64bit 整数42, -7
Float64bit 浮動小数3.14, -0.5
Bool真偽値true, false
Unit単一値()
Bytesバイト列リテラルなし、Bytes.from-text() で生成
TimeUNIX ナノ秒リテラルなし、now または Time.parse()

2.1.2 汎化型

用途
Map(K, V)キーは Eq、値は任意
Set(T)T は Eq
List(T)順序あり、インデックスアクセス可
Option(T)None または Some(T)
Result(T, E)Ok(T) または Err(E)
Tuple(T1, ..., Tn)固定長

2.1.3 ドメイン型(標準提供)

定義
HttpStatusnominal Int where between(100, 599)
HttpError{status: HttpStatus, message: Text, body: Option(Text)}
Urlnominal Text where url
Emailnominal Text where email
Uuidnominal Text where uuid
Durationnominal Int (ナノ秒)
Route{path: Text, params: Map(Text, Text), query: Map(Text, Text)}
FormDataMap(Text, FormValue)
FormValueTextV(Text) | NumberV(Float) | BoolV(Bool) | FileV(File)
File{name: Text, size: Int, type: Text, content: Bytes}

2.2 コレクションメソッド

2.2.1 Map(K, V)

keys                        : List(K)
values                      : List(V)
entries                     : List(Tuple(K, V))  ; 実装上 [[k, v], ...] の配列
size                        : Int
is-empty                    : Bool
has(k)                      : Bool
get(k)                      : Option(V)
get-or(k, default)          : V
insert(k, v)                : Map(K, V)        ; 純粋。新 Map を返す
remove(k)                   : Map(K, V)
update(k, expr)             : Map(K, V)        ; expr の中で $1 が現在値
merge(other)                : Map(K, V)
filter(pred)                : Map(K, V)        ; pred の中で $1=key, $2=value
map(expr)                   : Map(K, V')       ; expr の中で $1=key, $2=value

.entriesList(Tuple(K, V)) として 2 要素配列の列を返す。後続の map / sort-by / filter lambda はランタイム destructure により $1=key, $2=value で扱える:

strand
fn sortedByCreatedAt(m: Map(Id, Item)) -> List(Id)
   = m.entries.sort-by($2.createdAt).map($1)

get-orOption 用にも使える polymorphic method:

strand
m.get-or(k, default)         ; Map: 値がなければ default
opt.get-or(default)          ; Option: None なら default、Some(v) なら v

.filterList と Map の両方に対して使え、ランタイムが受信側の型を見て自動振り分けする (polymorphic dispatch):

  • 受信側が List → 各要素について pred($1) を評価、true の要素だけ残す
  • 受信側が Map → 各エントリについて pred($1, $2) (key, value) を評価、true のエントリだけ残す

例えば m.keys.filter(...) のようにチェーンしたとき、m.keysList(K) を返すため filter は List のシグネチャで動く。混在チェーンを書いても型に応じた挙動になる。

2.2.2 Set(T)

size                        : Int
has(x)                      : Bool
add(x)                      : Set(T)
remove(x)                   : Set(T)
toggle(x)                   : Set(T)
union(other)                : Set(T)
intersect(other)            : Set(T)
diff(other)                 : Set(T)
to-list                     : List(T)

2.2.3 List(T)

length                      : Int
is-empty                    : Bool
get(i)                      : Option(T)
head                        : Option(T)
tail                        : List(T)
last                        : Option(T)
push(x)                     : List(T)
prepend(x)                  : List(T)
concat(other)               : List(T)
slice(start, end)           : List(T)
reverse                     : List(T)
sort                        : List(T)          ; T は Ord
sort-by(expr)               : List(T)
unique                      : List(T)
map(expr)                   : List(T')
filter(pred)                : List(T)
contains(x)                 : Bool
find(pred)                  : Option(T)
fold(init, expr)            : Acc              ; expr の中で $1=acc, $2=elem
join(sep)                   : Text             ; T が Text
chunk(n)                    : List(List(T))
zip(other)                  : List(Tuple(T, U))

括弧なしショートカット: 引数なしメソッド(is-empty / length / reverse / sort / unique / head / tail / last)は () を省略して field のように書ける

strand
slot todos : List(Todo) = []
fn count() -> Int = todos.length              ; 括弧なし OK
fn empty?() -> Bool = todos.is-empty          ; 同上
fn norm() -> List(Todo) = todos.reverse       ; 同上

map / filter / sort-by の lambda 引数:

  • List 要素には $1 を、.entries 後の [k, v] ペアには $1=key, $2=value を束縛します(ランタイムが自動 destructure)
  • 例: m.entries.sort-by($2.createdAt).map($1)$1=key, $2=value

2.2.4 Option(T)

is-some                     : Bool
is-none                     : Bool
get                         : T               ; None なら panic(reducer 内のみ許可)
get-or(default)             : T
map(expr)                   : Option(T')
flat-map(expr)              : Option(T')
filter(pred)                : Option(T)
or(other)                   : Option(T)
to-list                     : List(T)

2.2.5 Result(T, E)

is-ok                       : Bool
is-err                      : Bool
get                         : T               ; Err なら panic
get-err                     : E               ; Ok なら panic
get-or(default)             : T
map(expr)                   : Result(T', E)
map-err(expr)               : Result(T, E')
flat-map(expr)              : Result(T', E)
or(other)                   : Result(T, E)
to-option                   : Option(T)

2.2.6 Text

length                      : Int
is-empty                    : Bool
upper                       : Text
lower                       : Text
trim                        : Text
starts-with(s)              : Bool
ends-with(s)                : Bool
contains(s)                 : Bool
split(sep)                  : List(Text)
replace(from, to)           : Text
slice(start, end)           : Text
parse-int                   : Option(Int)
parse-float                 : Option(Float)

2.2.7 Int / Float

abs, neg, min(b), max(b), clamp(lo, hi)
show, to-float (Int), to-int (Float, 切り捨て)

x.show全型共通の文字列化メソッド。Int / Float / Bool / variant / nominal すべて .show : Text を返す。Strand には to-text という名前は存在しない。

2.2.8 Time

Time.now                    : Time
Time.parse(text)            : Option(Time)    ; ISO8601
plus(duration)              : Time
minus(duration)             : Time
diff(other)                 : Duration
format(pattern)             : Text            ; "yyyy-MM-dd HH:mm"

2.2.9 Duration

Duration.ms(n)              : Duration
Duration.s(n)               : Duration
Duration.m(n)               : Duration   ; min と書いても可
Duration.h(n)               : Duration
Duration.d(n)               : Duration   ; days と書いても可
to-ms                       : Int

Time / Duration はランタイム上では raw ミリ秒数として表現される。time.plus(Duration.h(72)) のような演算は単なる ms 加算に展開される。

strand
fn isSoon(due: Time) -> Bool = due < now.plus(Duration.h(72))
fn elapsed(start: Time) -> Duration = now.diff(start)

2.3 tile プリミティブ要素

Strand の組み込みタイル。意味タグであり HTML タグの直訳ではない。

2.3.1 構造要素

要素役割主な props
pageアプリのルート画面title, class
region名前付きセクションaria-label, class
row水平レイアウトgap, align, justify
column垂直レイアウトgap, align, justify
stack重ね配置align
gridグリッドcols, gap
box汎用コンテナclass, style
cardカードclass
panelパネルclass
divider区切りorientation
scrollスクロールコンテナdirection, max-height

2.3.2 テキスト要素

要素役割主な props
textテキスト表示strike, bold, italic, size, color
heading見出しlevel (1-6)
linkリンクto, external
codeコードlang
markdownMarkdown 描画(内容は引数)

2.3.3 メディア要素

要素役割主な props
image画像src, alt, width, height, loading
iconアイコンname, size
video動画src, controls, autoplay

2.3.4 入力要素

要素役割主な props
buttonボタンtext, onClick, variant, disabled, loading
inputテキスト入力bind, placeholder, type (text/email/password/...), disabled
textarea複数行入力bind, rows, placeholder
checkチェックボックスvalue, onClick, label
radioラジオボタンname, value, selected, onClick
selectセレクトbind, options (List of {label, value}), placeholder
sliderスライダーbind, min, max, step
switchトグルvalue, onClick

2.3.5 フォーム

要素役割主な props
formフォーム(form をラップする tile に ui.submit(WrapperTile) で届く)id, auto-complete, novalidate
labelラベルfor
fieldsetフィールド集合legend
errorバリデーションエラー表示field

2.3.6 リスト・表

要素役割主な props
listリストordered
list-itemリスト項目
table
table-head表ヘッダ
table-body表本体
table-row表行
table-cell表セルcolspan, rowspan

2.3.7 オーバーレイ

要素役割主な props
modalモーダルopen, onClose, title
drawerドロワーopen, onClose, side
tooltipツールチップtext, placement
popoverポップオーバーopen, onClose, placement
toastトースト通知kind (info/success/warn/error), text

2.3.8 フィードバック

要素役割主な props
spinnerスピナーsize
progressプログレスバーvalue, max
skeletonスケルトンkind (text/box/circle)

2.3.9 制御要素

要素役割
when(cond, tile)cond が true なら tile を表示
if cond then tA else tB条件分岐
for x in coll tile反復
route-outletネストルートの出力位置
link(to=...)ルート遷移リンク

2.3.10 props の共通仕様

すべての tile は次の共通 props を受ける(ビルトイン):

prop意味
classTextスタイルクラス名
styleMap(Text, Text)インラインスタイル(最小限の使用を推奨)
ariaMap(Text, Text)ARIA 属性
keyTextfor 内で要素を一意に識別
test-idTextテスト用 ID

2.4 ビルトイン関数

2.4.1 ID 生成

TypeName.fresh()           : T            ; nominal 型の新 ID(UUIDv7)

2.4.2 時刻

now                        : Time          ; 現在時刻

2.4.3 型変換

TypeName.parse(text)       : Option(T)    ; nominal 型の文字列パース
TypeName.show(value)       : Text         ; 値の文字列表現

2.4.4 数学

math.abs, math.min, math.max, math.clamp
math.floor, math.ceil, math.round
math.sqrt, math.pow, math.log, math.exp
math.random                : Float        ; reducer 内のみ呼び出し可(effect 扱い)

2.4.5 文字列フォーマット

fmt(template, ...args)     : Text         ; "Hello {0}, you have {1}"

+Text と他型を結合した場合、自動で show 相当が呼ばれる。

2.4.6 デバッグ補助

trace(label, value)        : T            ; episode log にラベル付きで記録、値はそのまま返す
panic(message)             : never        ; プログラムを停止(reducer 内のみ)

2.5 標準 capability

app.caps で宣言できる capability の標準セット:

capability用途
http.get, http.post, http.put, http.patch, http.deleteHTTP リクエスト
storage.read, storage.writelocalStorage
session.read, session.writesessionStorage
indexed.read, indexed.writeIndexedDB
nav.push, nav.replace, nav.backルート遷移
clipboard.read, clipboard.writeクリップボード
notification.showデスクトップ通知
analytics.send計測イベント送信
log.writeログ出力
crypto.random, crypto.hash暗号
media.camera, media.microphoneメディアデバイス
geo.read位置情報
socket.connect, socket.sendWebSocket

未列挙の capability を app.caps に書くとコンパイルエラー。新規 capability の登録は v0.2 で plugin 経由を予定。


2.6 標準 effect

各 capability に対応する標準 effect。app.caps に capability があれば自動で使える。

→ 詳細仕様は ./http.md

2.6.1 ナビゲーション

strand
effect navigate    cap=nav.push     in={path: Text, params: Map(Text, Text)}  out=Unit
effect navigate-replace cap=nav.replace in={path: Text, params: Map(Text, Text)} out=Unit
effect navigate-back   cap=nav.back  in=Unit  out=Unit

2.6.2 トースト

strand
effect toast       cap=notification.show  in={kind: Text, text: Text}  out=Unit

2.6.3 ログ

strand
effect log         cap=log.write    in={level: Text, message: Text, data: Map(Text, Text)}  out=Unit

2.7 数値・通貨など、よく欲しがる型は意図的に未提供

Money, Percent, Decimal などはアプリ側で nominal を使って定義する。Strand は意見を持たない。

strand
type Cents = nominal Int where positive
type Yen   = nominal Int where positive