# 结果 Result 是 Deft 显式的成功/失败值:成功为 `%Ok{ :value v }`, 失败为 `%Err{ :message m }`。两者都是带标签映射,因此字段访问 (`$r~value`、`$r~message`)和模式匹配可直接作用于它们。下面这些 裸函数用于构造、检查和解包 Result,并已编译进每个运行时——无需 导入。围绕 `try`/`catch` 和返回 Result 函数的语言约定,参见 错误处理。 ## 函数 | 函数 | 用途 | |---|---| | `ok value` | 构造 `%Ok{ :value value }` | | `err message` | 构造 `%Err{ :message message }` | | `ok? x` | `x` 为 `%Ok` 时返回 true | | `err? x` | `x` 为 `%Err` 时返回 true | | `unwrap result ?default` | 提取 `%Ok` 的 `:value`、`%Err` 的 `:message`,或给定时的 `default` | | `throw value` | 抛出错误,跳转到最近的外层 `try` | | `ok! expr` / `$expr(ok!)` | 断言 `%Ok` 并返回其 `:value`;遇到 `%Err` 时从外层函数返回 | | `err! expr` / `$expr(err!)` | 断言 `%Err` 并返回其 `:message`;遇到 `%Ok` 时从外层函数返回 | `[ok v]` 等价于字面量 `%Ok{ value v }`,`[err m]` 等价于 `%Err{ message m }`;需要包装计算出的值时,这些构造函数很方便。 `unwrap` 返回 `%Ok` 的 `:value`;对于 `%Err`,它返回提供的默认值, 未提供默认值时返回 `:message`。默认值只在失败时使用,非 Result 值 原样通过。 `throw` 接受任意值。字符串是惯用形式,也是 catch 绑定的内容;抛出 完整的 `%Err` 映射可以保留额外字段:
[throw "not found"]
[throw %Err{ :message "invalid input" :code 422 }]
`ok!` 和 `err!` 由编译器拦截:`[ok! $expr]` 和后缀形式 `$expr(ok!)` 都会发出内联操作码而非函数调用,因此它们必须出现在函数体内,短路 返回才有意义。非 Result 值经过这两个动词时原样通过。 命名空间辅助函数 `result/map`、`result/sequence` 和 `result/traverse` 将函数提升到 Result 之上,并折叠 Result 集合; `and-then` 是单子绑定。它们都在参考文档中按符号逐一记录。 ## 示例
def fetch-user {|id^number|
    if ($id < 0) { return [err "bad id"] }
    [ok %{ :id $id :name "Alice" }]
}

set r [fetch-user 7]

[ok? $r]                                    # => true
[err? $r]                                   # => false
$r~value~name                               # => "Alice"
用谓词分支,或用 `match` 解构:
if [ok? $r] {
    echo "name:" $r~value~name
} else {
    echo "failed:" $r~message
}

match $r {
    %Ok{ value $v }       => echo "got $v"
    %Err{ message $m }    => echo "error: $m"
}
`unwrap` 是最快捷的出口;双参数形式为 `%Err` 提供默认值:
[unwrap [ok 42]]                            # => 42
[unwrap [err "nope"]]                       # => "nope" — the message
[unwrap [err "nope"] 0]                     # => 0 — the default
$r(unwrap)                                  # => %{ :id 7 :name "Alice" }
`ok!` 解包或从外层函数提前返回——这是让 Result 沿顺利路径串联的 惯用方式:
def inc-or-fail {|x|
    if ($x > 100) { return [err "too big"] } else { return [ok ($x + 1)] }
}

def go {|x|
    set v [ok! [inc-or-fail $x]]            # on %Err, go returns that Err
    ($v * 10)
}

[go 4]                                      # => 50
[go 200]                                    # => %Err{:message "too big"}
`err!` 是它的镜像:断言失败并提取消息,当值为 `%Ok` 时提前返回:
def describe {|r|
    set msg [err! $r]                       # on %Ok, describe returns that Ok
    [str "failed: " $msg]
}

[describe [err "disk full"]]                # => "failed: disk full"
[describe [ok 42]]                          # => %Ok{:value 42}
`try` 内的 `throw` 将控制权交给 catch:
try {
    [throw "x must be non-negative"]
} catch e {
    echo "caught:" $e                       # caught: x must be non-negative
}
## 另见 - 错误处理——`try`/`catch`、`throw`、Result 约定 - 类型——`%Ok`/`%Err` 是带标签映射;`type` 和 `is?` - 模式匹配——在 `match` 中解构 Result