# 任务
`task/` 动词是 `deftask` 产生的异步句柄的消费端:普通(并行)任务返回一个 future,它最终解析为单个值;而 `@stream` 返回一个流,在生产者产出值时逐步交付增量值。`spawn` 启动协作式协程,即 并发 中介绍的另一套模型。这些函数读取、轮询并关闭任务句柄;它们都是原生标准库,无需导入即可使用。
## 函数
| 函数 | 用途 |
|---|---|
| `task/stream-next $s` | 阻塞等待下一个流值;流耗尽时返回 `nil` |
| `task/stream-collect $s` | 所有剩余流值的列表 |
| `task/stream-try-next $s` | 非阻塞读取;没有就绪值时立即返回 `nil` |
| `task/stream-close $s` | 通知消费者已读取完毕;返回 `nil` |
| `task/stream-done? $s` | 生产者已完成时返回 `true`(不会再有值到来) |
| `task/future-ready? $f` | future 已解析(成功或被拒绝)时返回 `true`;从不阻塞 |
说明:
- 流生产者在自己的 OS 线程上运行,并带有一个缓冲区(`@buffer-size N`,默认 64)。`stream-done?` 报告的是生产者完成,而不是缓冲区为空:生产者结束后,仍留在缓冲区中的值可以用 `stream-next` 或 `stream-collect` 排空。用 `stream-try-next` 把流与其他工作交错进行,当你准备好消费时再用阻塞的 `stream-next`。
- `stream-close` 释放消费端;它不会杀死生产者。
- `future-ready?` 只报告状态 —— 要取值得调用 `await`。抛出了异常的任务同样会解析完成:`deftask` 的 future 以错误字符串解析,因此就绪的 future 不一定是成功的。
- 流的主体若抛出异常,该流会直接结束;错误被吞掉,消费者看到的是流正常完成。
## 示例
# Blocking consumer loop — stream-next returns nil when exhausted def s [deftask { @stream yield "a" yield "b" yield "c" }] set row [task/stream-next $s] while ![nil? $row] { echo "got" $row set row [task/stream-next $s] } # Non-blocking poll, then a bulk drain def s2 [deftask { @stream; yield 1; yield 2; yield 3 }] set first-value [task/stream-try-next $s2] # value, or nil if not ready [task/stream-done? $s2] # => true once the producer is done def rest [task/stream-collect $s2] # buffered remainder [task/stream-close $s2] # Futures settle independently of the consumer def f [deftask { (6 * 7) }] [task/future-ready? $f] # => false — still running [await $f] # => 42 [task/future-ready? $f] # => true — settled