章一覧

関数と制御フロー

処理を組み合わせ、条件に応じて分岐します。

4.1 関数を定義する

関数は fn で定義します。引数と返り値に型を書き、最後の式の値が結果になります。

ch04-fn.taut
fn double(x: i64): i64 {
  x * 2
}

fn add(a: i64, b: i64): i64 {
  a + b
}

let result := add(double(4), 3)
perform show("result", result)
実行結果
・ double
・ add

result = 11
result = 11

return は早く抜けたいときに使えます。短い関数では、最後の式を結果にするほうが読みやすくなります。

ch04-return.taut
fn early(x: i64): i64 {
  if x < 0 { return 0 }
  x
}

perform show("early", early(-3))
実行結果
・ early

early = 0
early = 0

4.2 if は値を返す式

ch04-if.taut
fn absolute(x: i64): i64 {
  if x < 0 { 0 - x } else { x }
}

let n := absolute(-12)
perform show("absolute", n)
実行結果
・ absolute

absolute = 12
absolute = 12

if の両側が値を返すので、その値を外側の式で使えます。単なる実行の枝分かれではなく、式の合成です。

4.3 関数も値

ラムダ(無名関数)は x => 式 と書きます。

ch04-lambda.taut
fn twice(f: (i64) -> i64, x: i64): i64 {
  f(f(x))
}

let result := twice(x => x + 10, 1)
perform show("twice", result)
実行結果
・ twice

twice = 21
twice = 21

関数型 (i64) -> i64 は、i64 を受け取って i64 を返す関数です。twice は関数を引数に受け取り、二回呼びます。

4.4 ループと停止性

ch04-while.taut
var i: i64 := 0
var sum: i64 := 0
while i < 4 {
  sum := sum + i
  i := i + 1
}
perform show("sum", sum)
実行結果
sum = 6
sum = 6

while は Div(止まらないかもしれないこと)という effect と関係します。この例では i が増えるのでループは終わりますが、一般の while には無限ループの可能性があります。Tauto は、その可能性を型と effect に反映する設計です。止まるかどうかの証明が必要な再帰は、第 15 章の整礎再帰で扱います。

演習 4.1:関数 maximum(a: i64, b: i64) -> i64 を、if 式で書いてください。