_.inject
Reduce by its old name, and the WIP edge you'll notice immediately
- obj
- memo
- *
_.inject is _.reduce by its old functional-programming name - foldl, if you're a Haskell person. Reduce is the operation that collapses a list into a single value: sum the numbers, join the strings, accumulate a dict from a list of records. Underscore.js shipped it as inject for ages, and this Python port keeps the legacy name alongside _.reduce.
Here's the honest part: this node is where the pack's "work in progress" warning becomes visible. The generated schema exposes only two inputs - obj and memo - and neither of those is the function that does the reducing. A fold without its fold function is just a box with a starting value, which is a real limitation.
How it works
The underlying method builds up a single result by threading an accumulator through each element:
def reduce(self, iteratee, memo=None):
# iteratee takes (memo, value, index) and returns memo
if memo is None:
memo = []
...
If no memo is supplied it defaults to [] - a list accumulator - and the iteratee (the (memo, value, index) function) is what decides how the fold behaves. inject is just this same method under its alias.
The inputs that matter
- obj - the primary input (
*), the collection to fold. Also accepts a_.CHAINto continue chaining. - memo - the starting accumulator. Typed
*, so it can be a number, a list, or an empty dict. This is the only real control you get on this node.
Output is a single * - the accumulated result, untyped.
The missing piece: there's no iteratee input on this node's schema. The generator produces a sibling _.reduce node (same pack, same category) that does expose iteratee plus an iteratee_json editor. So if you want a working fold, reach for _.reduce and treat _.inject as the legacy stub. That asymmetry is a perfect example of what "auto-generated, still WIP" means in practice - the two names are the same operation, but they got different schemas.
Where you'd actually use it
Once you have _.reduce with its iteratee, folding is genuinely powerful in ComfyUI: accumulate a list of seeds into a checksum, build a dict from a list of metadata records, join strings without a dedicated join node. _.inject specifically is the one you'll use when you want the default memo behavior (accumulating into a list) and don't need a custom function.
Installing
Part of comfy-ovum (MIT). ComfyUI Manager → search comfy-ovum → install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum
Underscore nodes need nothing extra - they run on the underscore3 port bundled in the repo. Pack-wide requirements.txt includes pymediainfo (system libmediainfo on Linux), tomli-w, requests, braceexpand, pillow, numpy, markdown-it-py, aiohttp.
Gotchas
The pack's own README calls the underscore family "an absolute disaster to use in production," and _.inject is the node where I'd most believe it: the missing iteratee input is a genuine rough edge, not a doc quirk. Keep it for experiments and simple default-memo folds; use _.reduce when you actually need control over the fold function.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| objopt | * | Primary input object. Also accepts _.CHAIN to continue chaining. | |
| memoopt | * | memo: JSON allowed for arrays/objects where applicable. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| * | * | — |