# 控制流

条件和循环都使用花括号。这样多写两笔，但读代码时很容易看出边界。

## 条件与循环

```kelyra
fn clamp_to_zero(value: i32) -> i32 {
  if value < 0 {
    return 0;
  } else {
    return value;
  }
}
```

`while` 在条件为真时重复执行；`break` 结束循环，`continue` 开始下一轮。

## `for ... in`

可迭代对象需要公开 `iter()`，其迭代器需要公开返回 `Maybe<T>` 的 `next()`；迭代器本身有 `next()` 时也能直接遍历。

```kelyra
import std.util.iterator;
import std.util.maybe;

class Cursor {
  current: i32;
  limit: i32;
  pub init(current: i32, limit: i32) {
    this.current = current;
    this.limit = limit;
  }
  pub fn next() -> std.util.maybe.Maybe<i32> {
    if current >= limit {
      return std.util.maybe.none<i32>();
    }
    let value = current;
    current = current + 1;
    return std.util.maybe.some<i32>(value);
  }
}

class Sequence {
  first: i32;
  limit: i32;
  pub init(first: i32, limit: i32) {
    this.first = first;
    this.limit = limit;
  }
  pub fn iter() -> Cursor {
    return Cursor(first, limit);
  }
}

fn twice(value: i32) -> i32 { return value * 2; }
fn above_two(value: i32) -> bool { return value > 2; }

@main
fn main() -> i32 {
  let total: i32 = 0;
  for item in Sequence(1, 6) {
    if item == 2 {
      continue;
    }
    if item == 5 {
      break;
    }
    total = total + item;
  }
  if total != 8 {
    return 1;
  }
  let sequence = Sequence(0, 3);
  for item in &sequence {
    total = total + item;
  }
  if total != 11 {
    return 2;
  }
  let numbers: [3]i32;
  numbers[0] = 1;
  numbers[1] = 2;
  numbers[2] = 3;
  let view: []const i32 = numbers[:];
  for item in std.util.iterator.slice<i32>(view) {
    total = total + item;
  }
  if total != 17 {
    return 3;
  }
  for item in std.util.iterator.pipe<i32>(view).map(twice).filter(above_two).take(1) {
    total = total + item;
  }
  if total != 21 {
    return 4;
  }
  let cursor = Cursor(0, 2);
  for item in &cursor {
    total = total + item;
  }
  if total != 22 {
    return 5;
  }
  return 42;
}
```
标准库的 `std.util.iterator` 提供切片适配器与惰性 `pipe`。目前 `map` 回调须是无捕获函数，且保持元素类型不变。

## 枚举与 `match`

纯枚举可以给成员指定整数值。`match` 支持枚举、布尔值和整数等值匹配；对枚举与布尔值要覆盖所有可能分支。

```kelyra
enum Color: u8 {
  Red,
  Green = 3,
  Blue,
}

enum Status {
  Ready,
  Done,
}

fn read_once(counter: *i32) -> Color {
  *counter = *counter + 1;
  return Color.Green;
}

fn early(flag: bool) -> i32 {
  match flag {
    true => {
      return 2;
    },
    false => {
      return 3;
    },
  };
}

@main
fn main() -> i32 {
  let status: Status;
  let counter: i32 = 0;
  let color: i32 = match read_once(&counter) {
    Color.Red => 1,
    Color.Green => {
      let value: i32 = 2;
      value
    },
    Color.Blue => 3,
  };
  let truth: i32 = match Color.Red == Color.Red {
    true => 1,
    false => 0,
  };
  let number: i32 = match 7 {
    3 => 10,
    _ => 4,
  };
  let initial: i32 = match status {
    Status.Ready => 1,
    Status.Done => 0,
  };
  let code: i32 = (Color.Blue as u8) as i32;
  return color + truth + number + initial + counter + early(false) + code;
}
```
当前没有带载荷的枚举、范围模式和守卫。更多细节见[枚举与 match 设计说明](https://github.com/z8z6/kelyra/blob/main/compiler/doc/enum-match.md)。
