# 元编程 Deft 通过 `@` 装饰器、`meta` 访问器和 `info/*` 命名空间公开自身的 元数据与反射层。它们共同覆盖内省(这个值知道自身哪些信息?)与 标注(工具应如何处理它?)。特殊形式(special form)—— 编译器保留、 会被脱糖为内部 IR 的名称 —— 也在此一并记录。 ## 装饰器:`@`-标签 函数体中可以包含任意数量的 `@key value` 行。键成为元数据; 值被附加到其上。`@doc` 最为常见;任意标签也同样可用。
def greet {|name^string|
    @doc "Print a greeting."
    @since "1.2.0"
    @category :friendly
    echo "Hello, $name!"
}
`@doc` 接受字符串(多个时会被连接)或结构化映射:
def create-user {|name^string email^string|
    @doc {
        :description "Create a user record."
        :params %{
            :name "User's full name"
            :email "Contact email"
        }
        :returns %User
    }
    %User{ :name $name :email $email }
}
### 获取元数据 `meta` 读取单个键;`info/props` 返回完整的元数据映射:
echo [meta $greet "doc"]                       # => "Print a greeting."
echo [meta $greet "since"]                     # => "1.2.0"
echo [info/props $greet]
# => %{ :doc "Print a greeting." :since "1.2.0" :category :friendly }
### 装饰器的其他使用场景 | 标签 | 使用者 | |---|---| | `@doc` | 编辑器悬停提示、REPL 帮助、`info/props`、MCP 工具描述 | | `@rpc true` | 运行时 RpcRegistry —— 将函数暴露给 `rpc` | | `@command` | CLI 子命令注册 | | `@private` / `@internal` | 文档工具 —— 标记为非公开 | | `@since` / `@deprecated` | 版本追踪 | | `@bench` | 为运行器标记基准测试 | ## `info/*` 命名空间 `info/*` 公开运行时的符号表与模块表。 | 函数 | 返回值 | |---|---| | `info/modules` | 已加载模块名称的列表 | | `info/defs` | 当前命名空间中的 def | | `info/vars` | 当前命名空间中的 var(模块局部变量) | | `info/types` | 已注册的类型 | | `info/protocols` | 已注册的协议 | | `info/props` | 某个值的完整元数据映射 | | `info/sig` | 函数签名 | | `info/source` | def 的源代码(若可用) | | `info/resolve` | 将名称解析到其源码 |
[info/defs]                                    # => @{ greet create-user ... }
[info/types]                                   # => @{ User Point ... }
[info/protocols]                               # => @{ Drawable Keyable ... }
[info/sig $greet]                              # => function with 1 param
[info/source $greet]                           # => source text
## 对值进行反射
[type 42]                                      # => "number"
[type "hi"]                                    # => "string"
[type %User{...}]                              # => "User"
[type @{ 1 2 }]                                # => "list"
[type ^{:a :b}]                                # => "set"

[is? "number" 42]                              # => true
[is? "User" $alice]                            # => true
[satisfies? $p "Drawable"]                     # => true if $p's type impls Drawable
[nil? $x]                                      # => true if nil
[empty? $xs]                                   # => true if empty
[future? $f]                                   # => true if a Future
[keyword? :foo]                                # => true
## 特殊形式 这些是编译器保留的名称。它们不是函数;它们会被脱糖为内部 IR, 或触发特定的编译器行为。 ### 变量绑定 | 形式 | 用途 | |---|---| | `def name value` | 模块作用域绑定 | | `set name value` | 局部重新绑定 | | `set name^type value` | 带类型的重新绑定(在运行时校验) | ### 集合构造器 | 形式 | 用途 | |---|---| | `@{ ... }` | 列表字面量 | | `%{ ... }` | 映射字面量 | | `^{ ... }` | 集合字面量 | | `%Tag{ ... }` | 标签映射字面量 | ### 控制流 | 形式 | 用途 | |---|---| | `if cond { ... } else { ... }` | 条件分支 | | `match expr { pat => result ... }` | 模式分派 | | `for x in $xs { ... }` | 集合迭代 | | `while cond { ... }` | 条件循环 | | `try { ... } catch e { ... }` | 错误处理 | | `defer { ... }` | 退出时清理 | | `return expr` | 提前返回 | | `break` / `continue` | 循环控制 | | `throw value` | 抛出错误 | ### 函数定义 | 形式 | 用途 | |---|---| | `def name { \|params\| body }` | 函数 | | `def name { \|params\| body1 \|params\| body2 }` | 多参数个数函数 | | `defcoro name { ... }` | 协程 | | `deftask { body }` | 异步任务(也是函数位置形式) | | `defworker "path.dft" ?n` | 持久化工作进程 / 池(函数位置形式;见 defworker) | | `defmacro name { \|params\| body }` | 宏 | | `deftype Name %{ ... }` | 记录类型 | | `defprotocol Name %{ ... }` | 协议规范集合 | | `defimpl Type Protocol { ... }` | 附加行为 | | `defmethod Type name { ... }` | 添加单个方法 | | `defsuite "name" { ... }` | 测试套件 | | `deftest "name" { ... }` | 测试用例 | | `defbench "name" { ... }` | 基准测试用例 | > 以下形式出现在一些旧文档中,但在当前语言中并不存在: > `defgen`、`defwait`、`defgroup`、`defasync`、 > `chan`、`<-`、`select`(channel 形式)、`receive`、`send`。 > 受支持的原语见并发。 ### 模块系统 | 形式 | 用途 | |---|---| | `import "path" as alias` | 加载并设置别名 | | `from "path" import @{ names }` | 引入特定名称 | | `implements Interface` | 模块符合性(在加载时检查) | | `in-ns "name"` | 切换命名空间 | ### 运算符(参数个数固定) | 形式 | 用途 | |---|---| | `+ - * /` | 算术 | | `mod` | 取模 | | `== != < > <= >=` | 比较 | | `and or not` | 布尔运算 | | `& \| ^ << >>` | 位运算 | | `..` | 范围(在模式和中缀内) | ### 内部 IR 形式 编译器会生成少量以 `__` 为前缀的 IR 节点,在阅读生成代码或宏输出时 可能会遇到: | 形式 | 用途 | |---|---| | `__make-tagged-map` | 构造标签映射(由 HTML/SQL 块使用) | | `__shell-exec` | Shell 捕获 `[|cmd]` | | `__postfix-*` | 后缀糖 `$x(call)` | | `__capture` | 闭包字面量 | | `__import-file` / `__import` / `__refer` | 模块加载器钩子 | | `__implements` | `implements` 的脱糖 | | `__source` | 源码追踪节点 | | `__defsuite` / `__deftest` / `__defbench` | 测试脚手架 | 你不需要直接编写这些形式;在此记录它们是为了让宏输出与错误追踪 可被解读。 ## 在实践中使用元数据 ### 编辑器 / 工具 文档工具会遍历 `info/defs` 并提取 `@doc` 字符串来构建 API 参考。 MCP 集成(见 MCP)使用 `@doc` 描述暴露给语言模型的工具。 ### 自定义分派 为函数标注任意元数据,然后据此分派:
def handler {|req|
    @route "/users/:id"
    @method :GET
    # ...
}

# Walk all defs, find handlers by their @route metadata
def routes []
for name [info/defs] {
    set fn [info/resolve $name]
    set route [meta $fn "route"]
    if $route { $routes << @{ $route $fn } }
}
### 运行时版本管理
defn deprecated-op {|x|
    @deprecated "use new-op instead"
    @since "0.3.0"
    # ...
}
代码检查工具可以遍历 `info/defs`,对任何调用了标记为 `@deprecated` 的函数的调用发出警告。 ## 快速参考 | 形式 | 用途 | |---|---| | `@key value`(在 def 函数体内) | 附加元数据 | | `[meta $fn "key"]` | 读取一条元数据 | | `[info/props $fn]` | 读取全部元数据 | | `[info/defs]` / `[info/types]` / `[info/protocols]` | 命名空间内容 | | `[info/sig $fn]` / `[info/source $fn]` | 函数信息 | | `[type x]` / `[is? "Type" x]` / `[satisfies? x "Protocol"]` | 类型反射 |