Skuld.Effects.FxFasterList (skuld v0.1.26)
View SourceFxFasterList - High-performance effectful list operations.
An optimized variant of FxList that uses Enum.reduce_while for
better performance. Best for computations that don't need resumable
Yield/Suspend semantics.
When to Use FxFasterList vs FxList
| Feature | FxFasterList | FxList |
|---|---|---|
| Performance | ~0.1 µs/op | ~0.2 µs/op |
| Throw (error handling) | ✓ Works | ✓ Works |
| Yield (suspend/resume) | ✗ Limited* | ✓ Full |
| Memory | Lower | Higher |
*FxFasterList suspends but loses list context - resume returns only the single element's result, not the full list.
Use FxFasterList when:
- Performance is critical
- You only use Throw for error handling (not Yield)
- You don't need to resume suspended computations
Use FxList when:
- You need resumable Yield/Suspend semantics (recommended default)
- You want natural control effect propagation
Operations
fx_map(enumerable, f)- Map effectful function over enumerablefx_reduce(enumerable, init, f)- Reduce with effectful functionfx_each(enumerable, f)- Execute effectful function for each element (returns :ok)fx_filter(enumerable, pred)- Filter with effectful predicate
Example
import Skuld.Syntax
defcomp process_users(user_ids) do
users <- FxFasterList.fx_map(user_ids, fn id ->
comp do
user <- fetch_user(id)
count <- State.get()
_ <- State.put(count + 1)
return(user)
end
end)
return(users)
endImplementation
FxFasterList uses Enum.reduce_while to iterate, running each element's
computation to completion before moving to the next. This avoids
building continuation chains, providing ~0.1 µs/op constant cost.
Control effects (Throw, Cancelled, Suspend) are detected via ISentinel
predicates (error?/1 and suspend?/1) and handled explicitly - errors
propagate correctly, but Suspend loses the iteration context.
Summary
Functions
Execute an effectful function for each element, discarding results.
Filter an enumerable with an effectful predicate.
Map an effectful function over an enumerable.
Reduce an enumerable with an effectful function.
Functions
@spec fx_each(Enumerable.t(), (term() -> Skuld.Comp.Types.computation())) :: Skuld.Comp.Types.computation()
Execute an effectful function for each element, discarding results.
Returns a computation that produces :ok.
Each element's computation runs to completion before the next begins.
Example
FxFasterList.fx_each(1..1000, fn i ->
comp do
n <- State.get()
_ <- State.put(n + 1)
return(:ok)
end
end)
# => computation returning :ok
@spec fx_filter(Enumerable.t(), (term() -> Skuld.Comp.Types.computation())) :: Skuld.Comp.Types.computation()
Filter an enumerable with an effectful predicate.
Each element's predicate runs to completion before the next begins.
Example
FxFasterList.fx_filter([1, 2, 3, 4], fn x ->
comp do
threshold <- Reader.ask()
return(x > threshold)
end
end)
# With threshold=2 => computation returning [3, 4]
@spec fx_map(Enumerable.t(), (term() -> Skuld.Comp.Types.computation())) :: Skuld.Comp.Types.computation()
Map an effectful function over an enumerable.
Returns a computation that produces a list of results. Each element's computation runs to completion before the next begins, avoiding continuation chain buildup.
Example
FxFasterList.fx_map([1, 2, 3], fn x ->
comp do
count <- State.get()
_ <- State.put(count + 1)
return(x * 2)
end
end)
# => computation returning [2, 4, 6]
@spec fx_reduce(Enumerable.t(), term(), (term(), term() -> Skuld.Comp.Types.computation())) :: Skuld.Comp.Types.computation()
Reduce an enumerable with an effectful function.
Each element's computation runs to completion before the next begins.
Example
FxFasterList.fx_reduce([1, 2, 3], 0, fn x, acc ->
comp do
_ <- Writer.tell("processing #{x}")
return(acc + x)
end
end)
# => computation returning 6