Skuld.Effects.FxFasterList (skuld v0.1.26)

View Source

FxFasterList - 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

FeatureFxFasterListFxList
Performance~0.1 µs/op~0.2 µs/op
Throw (error handling)✓ Works✓ Works
Yield (suspend/resume)✗ Limited*✓ Full
MemoryLowerHigher

*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 enumerable
  • fx_reduce(enumerable, init, f) - Reduce with effectful function
  • fx_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)
end

Implementation

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

fx_each(enumerable, f)

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

fx_filter(enumerable, pred)

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]

fx_map(enumerable, f)

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]

fx_reduce(enumerable, init, f)

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