Parametric Aspects
How Parametric Dispatch Works
Section titled “How Parametric Dispatch Works”Den inspects function arguments at evaluation time using builtins.functionArgs.
A function’s required parameters determine which contexts it matches:
# Matches: {host}, {host, user}, {host, user, foo}({ host, ... }: { nixos.x = host.hostName; })
# Matches: {host, user} only(den.lib.perUser ({ host, user }: { nixos.x = user.userName; }))
# Matches: {home} only(den.lib.perHome ({ home }: { homeManager.x = home.userName; }))The canTake Function
Section titled “The canTake Function”den.lib.canTake (nix/fn-can-take.nix) checks if a function’s required arguments
are satisfiable with given parameters:
canTake { host = ...; } ({ host, ... }: ...) # => true (atLeast)canTake { host = ...; } ({ host, user }: ...) # => false (user missing)
canTake.exactly { host = ...; } ({ host }: ...) # => truecanTake.exactly { host = ...; foo = ...; } ({ host, ... }: ...) # => false (extras)canTake.atLeast— all required params are present (default).canTake.exactly— required params match provided params exactly.
The take Utilities
Section titled “The take Utilities”den.lib.take wraps canTake into aspect-ready helpers:
# Apply fn only if ctx satisfies atLeastden.lib.take.atLeast fn ctx
# Apply fn only if ctx satisfies exactlyden.lib.take.exactly fn ctxThese are used inside includes to control when a function activates.
The parametric Constructor
Section titled “The parametric Constructor”den.lib.parametric changes an aspect __functor which processes
its includes list through parametric dispatch:
den.lib.parametric { nixos.foo = 1; # owned config, always included includes = [ { nixos.bar = 2; } # static, always included ({ host }: { nixos.x = host.name; }) # parametric, host contexts only ({ user }: { homeManager.y = 1; }) # parametric, user contexts only ];}When the aspect’s __functor is called with a context, it filters includes
based on argument compatibility and returns only matching entries.
Parametric Variants
Section titled “Parametric Variants”| Constructor | Behavior |
|---|---|
parametric | Default. Includes owned classes + static includes + function includes with context matching atLeast. |
parametric.atLeast | Does NOT include owned classes nor static includes. Only function matching atLeast the context. |
parametric.exactly | Like atLeast but using canTake.exactly for match. |
parametric.fixedTo attrs | Like parametric default but ignores any context and always uses the given attrs . |
parametric.expands attrs | Like parametric, but extends the received context with attrs before dispatch. |
Example: Context-aware battery
Section titled “Example: Context-aware battery”This is a pattern used by many of our built-in batteries, be sure to see their code as example.
den.lib.parametric.exactly { includes = [ ({ user, host }: { ... }) ({ home }: { ... }) ];};The first function runs for every {host, user} context. The second only
runs for {home} (standalone home-manager) contexts. No mkIf needed.