# deftask Create an async task — a Future or stream depending on the body's decorators. ## Syntax
[deftask { body }]                             # run body on a fresh OS thread
[deftask { @parallel body }]                   # explicit equivalent of the default
[deftask { @stream body }]                     # stream of incremental results
[deftask { @stream @buffer-size 128 body }]    # stream with custom buffer
A plain `deftask` is parallel by default: the closure's bytecode is deep-copied into a fresh runtime on a new OS thread, and the call returns a pending Future. `@parallel` is accepted as an explicit marker for the same behavior. Mode decorators are carried as decorator metadata on the closure — the same `@`-decorator mechanism defs use (`@async`, `@generator`, `@rpc`). Put them at the top of the body, each on its own line or separated by `;`:
[deftask {
    [http/get "https://api.example.com/a"]
}]

[deftask { @stream; yield 1 }]
## Decorators | Decorator | Effect | |-----------|--------| | `@parallel` | Explicit form of the default: deep-copy the closure's bytecode into a fresh runtime on a new OS thread; returns a pending Future. | | `@stream` | Run the body on a new OS thread; `yield` values are pushed into a buffered stream. | | `@buffer-size N` | (with `@stream`) Stream buffer size (default 64). | Task bodies must be self-contained: native stdlib functions are available, but captured locals and user-defined functions do not cross into the child runtime. (For full module access use `defworker`.) ## Examples
def x 6   # global — snapshotted into the child runtime
def fut [deftask { ($x * $x) }]
echo [await $fut]

def ps [deftask { [http/get "https://api.example.com/a"] }]
[await $ps]

def s [deftask { @stream
    @buffer-size 128
    yield 1
    yield 2
    yield 3
}]
set row [task/stream-next $s]
while (not [nil? $row]) {
    # ... process $row ...
    set row [task/stream-next $s]
}
# or just: def rows [task/stream-collect $s]
## Returns A Future (`deftask` / `@parallel`) or a stream (`@stream`). ## Errors How a throw inside the task body surfaces depends on the mode: - `deftask` / `@parallel` — the future resolves with the error string (e.g. `"boom (line 1)"`); `await` returns it as the task's value. It does not re-throw at the await site. - `@stream` — the stream simply ends; the error is swallowed.
set v [await $f]
if [is? "string" $v] {
    echo "task failed:" $v
}
## See Also `await`, `spawn`, `resume`, `async`, `defworker`