# 函数

## 功能
函数用于把一段可复用逻辑封装起来。BT 的函数体、箭头函数代码块、`if` 代码块和普通 `{}` 代码块都有返回值：没有显式 `return` 时，最后一条语句的值就是返回值。

## 语法
```bt
fn name(param1, param2 = default_value) {
    statement
    result
}

fn(param1, param2) {
    result
}

value -> value * 2

(value, key) -> {
    value + ':' + key
}
```

## 参数
- `name`: 函数名。函数声明必须有名称。
- `param`: 参数名。多个参数用逗号分隔。
- `default_value`: 默认参数值。调用时没有传入对应参数，就使用默认值。

## 返回值
`Fn`：函数值。函数被调用后返回函数体最后一条语句的值；使用 `return` 时，会立即结束当前函数并返回指定值。

## 函数声明
函数声明适合定义会被多次调用的逻辑。

```bt
fn add(a, b) {
    a + b
}

sum = add(1, 2)
```

函数体不需要为了返回结果专门写 `return`。下面两个函数的返回值一样：

```bt
fn add(a, b) {
    a + b
}

fn add_by_return(a, b) {
    return a + b
}
```

## 默认参数
参数可以设置默认值。

```bt
fn hello(name = 'BT') {
    'Hello ' + name
}

a = hello()
b = hello('Tom')
```

## 匿名函数
匿名函数没有函数名，可以赋值给变量，也可以直接作为回调参数传入。

```bt
double = fn(value) {
    value * 2
}

a = double(3)
b = [1, 2, 3].map(fn(value) { value * 2 })
```

匿名函数也支持多个参数和默认参数。

```bt
join = fn(left, right = 'BT') {
    left + right
}

result = join('Hello ', 'World')
```

## 箭头函数
箭头函数适合写短回调。它本质上也是函数值，可以作为参数传给 `map`、`filter`、`each`、对象方法等需要回调的地方。

### 单参数表达式
单个参数可以不写括号，箭头右侧是表达式时，表达式的值就是返回值。

```bt
nums = [1, 2, 3]
result = nums.map(value -> value * 2)
```

### 单参数代码块
箭头右侧也可以写 `{}`。代码块中可以写多条语句，最后一条语句就是返回值。

```bt
nums = [1, 2, 3]
result = nums.map(value -> {
    next = value * 2
    next + 1
})
```

### 多参数表达式
多个参数必须用 `()` 包起来。数组回调常见参数是 `value, index, current`，对象回调常见参数是 `value, key, current`。

```bt
nums = [10, 20, 30]
result = nums.map((value, index) -> value + index)

user = {name: 'BT', age: 1}
result = user.map((value, key) -> key + '=' + string(value))
```

### 多参数代码块
多参数箭头函数同样支持 `{}`。

```bt
user = {name: 'BT', age: 1}

result = user.map((value, key) -> {
    prefix = key + ':'
    prefix + string(value)
})
```

### 无参数箭头函数
没有参数时使用空括号。

```bt
create_name = () -> 'BT'
name = create_name()
```

### 默认参数箭头函数
带括号的箭头函数参数也可以设置默认值。

```bt
format = (name, prefix = 'Hello ') -> prefix + name
text = format('BT')
```

## 调用方式
函数可以用多种方式调用。

```bt
fn add(a, b) {
    a + b
}

// 通过函数名调用
a = add(1, 2)

// 函数赋值给变量后调用
sum = add
b = sum(3, 4)

// 匿名函数立即赋值后调用
double = fn(value) { value * 2 }
c = double(5)

// 箭头函数赋值后调用
triple = value -> value * 3
d = triple(6)

// 作为回调传入
items = [1, 2, 3]
e = items.map((value, index) -> value + index)

// 使用 call 动态调用
f = call(add, 7, 8)
```

## return
`return` 会立即结束当前函数。适合在命中某个条件后提前返回。

```bt
fn check(user) {
    if !user {
        return '未登录'
    }
    '已登录'
}
```

## 注意事项
- 普通函数声明使用 `fn name(...) { ... }`。
- 匿名函数使用 `fn(...) { ... }`。
- 单参数箭头函数可以写成 `value -> value * 2` 或 `value -> { value * 2 }`。
- 多参数箭头函数需要写成 `(value, key) -> value` 或 `(value, key) -> { value }`。
- `{}` 代码块会返回最后一条语句的值，不需要额外写 `return`。
- `return` 只能用于提前结束当前函数，不建议在简单表达式回调中滥用。
