Yield
View Source< Command & Transaction | Index | Coroutine >
Yield suspends a computation mid-flight, returning control to the caller with a value. The caller can later resume the computation with a response.
This is the primitive that bridges the foundational effects to the
coroutine system. Coroutine, FiberPool, AsyncCoroutine, and
EffectLogger all build on top of Yield.
Basic usage
defcomp ask_name do
name <- Yield.yield(:get_name) # suspend, return :get_name
{:ok, "Hello, #{name}!"}
endRunning it:
{%Comp.ExternalSuspend{value: :get_name, resume: resume}, env} =
ask_name() |> Yield.with_handler() |> Comp.run()
# Later, when we have a name:
{result, _env} = resume.("Alice")
# result == {:ok, "Hello, Alice!"}The computation pauses at Yield.yield(:get_name). The caller gets an
ExternalSuspend with the yielded value and a resume function. Calling
resume.(value) continues the computation from where it left off.
Operations
value <- Yield.yield(:ask_user) # suspend with a value
value <- Yield.yield(:ask_user, data) # suspend with data payload
Yield.respond(:answer) # respond to source (bidirectional)Patterns
Multi-step wizards
defcomp wizard do
name <- Yield.yield(:get_name)
email <- Yield.yield(:get_email)
{:ok, %{name: name, email: email}}
endCollect pattern
Yield.collect feeds a stream of inputs into a yielding computation,
collecting the final result:
Yield.collect(wizard(), ["Alice", "alice@example.com"])
# => {:ok, %{name: "Alice", email: "alice@example.com"}}Feed pattern
Yield.feed links two yielding computations — the output of one feeds
into the yield of another:
Yield.feed(producer(), consumer())Handler
computation |> Yield.with_handler()Yield.with_handler converts Yield.yield calls into ExternalSuspend
sentinels. Handler order relative to other effects doesn't matter — each
handler manages its own effect independently.