ilusm.dev

dst

Named operation hooks and message dispatch - create named nodes that hold a map of operation thunks, register handlers by operation name, call or safe-try a named operation with a message, broadcast a message to all operations, and pipe a value through a sequence of named operations.

Load with: use dst

What this module does

dst provides a lightweight message-dispatch layer where each "node" is a named entity that holds a dictionary of named operation handlers. You register thunks (functions taking a message) for specific operation names, then dispatch calls by name. Results are wrapped in res ok/bad envelopes.

This pattern is useful for building extensible systems where components register capabilities by name and callers dispatch to them without needing direct function references - similar to a mini actor model or event-handler registry.

Quick example

use dst

# Create a node
n = dstne("mynode")

# Register operations
n = dston(n, "greet", \(msg) "Hello, " + msg)
n = dston(n, "shout", \(msg) txt.up(msg))

# Check operation presence
prn(dstha(n, "greet"))   # tru
prn(dstha(n, "missing")) # fls

# List all operations
prn(dstop(n))  # ["greet", "shout"]

# Call an operation
r = dstca(n, "greet", "world")
prn(r.val)  # "Hello, world"

# Safe-try (returns try-result, not res envelope)
t = dsttr(n, "shout", "hello")

# Broadcast same message to all operations
all = dstbr(n, "hello")

# Pipe a value through a sequence of ops
result = dstpi(n, ["greet", "shout"], "alice")

Functions

Node lifecycle

dstne(node_id)

Creates a new dispatch node with the given string ID and an empty hooks map: {id, hooks: {}}.

dstid(node)

Returns the node's ID string.

Hook registration

dston(node, op_name, thunk)

Registers a handler function for operation op_name. The thunk receives a single message argument and returns the result. Errors via eru.bang if types are wrong. Returns the updated node.

dstha(node, op_name)

Returns tru if a handler is registered for op_name.

dstop(node)

Returns a list of all registered operation names.

Dispatch

dstca(node, op_name, message)

Calls the handler for op_name with message. Returns res.ok(result) on success or res.bad("dst: no {op}") if the operation is not registered.

dsttr(node, op_name, message)

Like dstca but wraps the call in try and unwraps the res envelope. Returns a {val, err} try-result - errors do not propagate.

Broadcast and pipeline

dstbr(node, message)

Calls every registered operation with the same message. Returns res.ok(results_list) where results_list is the list of res envelopes for each operation in registration order.

dstpi(node, op_names, seed_value)

Pipes a value through a sequence of named operations. Starts with res.ok(seed_value), calls each operation in order passing the previous result's value. Short-circuits on the first res.bad. Returns the final res envelope.

Notes

  • Results from dstca and dstbr are res envelopes - use res.ok, res.bad, res.isok, and res.val to work with them.
  • Requires eru, res, and trl.