06 — ミューテーション・region・エスケープ
前: 型と文字列
English version: 06_mutation.vibe.md
vibe は既定で不変で、ミューテーションは意図的に小さく作られています。局所的 であり、関数の effect row には決して現れません。内部でカウンタを使う関数の 署名は使わない関数と同じです — 外から見て違いがないからです。
カウンタ
let mut は、そのブロックが終わるまで書き換え可能な束縛を作ります:
fn main with Console {
let y = {
let mut v = 0
v += 1
v + 1
}
println("y = \{y}")
}
y = 2
y はただの不変な Int です。可変な束縛は波括弧の中にしか存在せず、
コンパイラはそれをただの wasm local に置きます — このためのアロケーション
は起きません。
配列を伸ばす
ここでは束縛が不変で中身が伸びます。Array::push はその場で追加
するので、その配列を指すすべての名前が新しい要素を見ます — 渡した先の関数を
含めて:
fn grow(xs: Array[Int]) -> Unit {
Array::push(xs, 9)
}
fn main with Console {
let xs = [
1
]
grow(xs)
println("length = \{Array::length(xs)}, last = \{Array::get(xs, 1)}")
}
length = 2, last = 9
ここは意識しておく価値があります。xs は共有であってコピーではありません。
自分専用のコピーが欲しければ、明示的に作ってください。
書き込めるフィールド
変わるものが値の一部なら、そのフィールドを mut と宣言します。書き込みは
すべてのエイリアスから観測されます — 書き込み前に取ったものも含めて:
struct Counter {
mut n: Int
} derive (Show)
fn bump(c: Counter) -> Unit {
c.n = c.n + 1
}
fn main with Console {
let c = Counter::{
n: 10
}
let alias = c
bump(c)
bump(c)
println("c.n = \{c.n}, alias.n = \{alias.n}")
}
c.n = 12, alias.n = 12
ローカルで済むなら let mut を選んでください。mut フィールドは、その値を
持っている誰もが書き込めるセルであり、カウンタよりずっと大きな主張です。
エスケープとは捕獲のこと
let mut が本当にローカルかどうかを決める規則は1つです。束縛より長生き
しうるクロージャがそれを捕獲したら、もうローカルではありません。その場合
コンパイラは、クロージャから届くようにヒープへ置きます。
どの束縛がそうなったかを当てる必要はありません:
vibe escapes file.vibe
エスケープする let mut を1件1行で出力し、出力が空ならファイル中の
let mut はすべてただのローカルです。もう1つの形式があります:
vibe escapes --strict file.vibe
既定は「codegen が何をするか」に答えます — 迷ったら box するので、既定は
多めに報告します。--strict は「そのクロージャが本当にこの束縛に届くか」に
答え、名前が単にシャドウされているだけの場合を差し引きます。コストが気に
なるなら既定を、誰が何を書けるかが気になるなら --strict を訊いてください。
Region
並行処理では同じ考えのより強い版が要ります。タスクグループに属する作業用の
値は、グループより長生きしてはいけません。TaskGroup::run はそのために
新しい region タグを作り、本体の戻り値を通じて値が抜け出すのを拒否します。
機構が意味を持つ場所、並行処理で扱います。
どれを選ぶか
一通り見た上で:
| やりたいこと | 使うもの |
|---|---|
| 1つの関数の中のカウンタや累算器 | let mut |
| 配列を組み立ててから読む | ArrayBuilder を freeze する |
| テキストを組み立てる | StringBuilder |
| フィールドが時間とともに変わる値 | struct S { mut f: T } |
| 呼び出しをまたぐ、仲介された状態 | effect と handle |
大半のコードは1行目で足ります。ビルダーは コレクションで扱います。
次: 構造体・列挙・match。