added overridableDelayableArgs replacing applyAndFun

svn path=/nixpkgs/trunk/; revision=14424
This commit is contained in:
Marc Weber 2009-03-06 23:21:12 +00:00
parent e917282535
commit be3a9f2346
1 changed files with 53 additions and 19 deletions

View File

@ -35,22 +35,56 @@ rec {
# now add the function with composed args already applied to the final attrs # now add the function with composed args already applied to the final attrs
setAttrMerge "passthru" {} (f arg) ( x : x // { function = foldArgs merger f arg; } ); setAttrMerge "passthru" {} (f arg) ( x : x // { function = foldArgs merger f arg; } );
# returns f x // { passthru.fun = y : f (merge x y); } while preserving other passthru names. # predecessors: proposed replacement for applyAndFun (which has a bug cause it merges twice)
# example: let ex = applyAndFun (x : removeAttrs x ["fixed"]) (mergeOrApply mergeAttr) {name = 6;}; # the naming "overridableDelayableArgs" tries to express that you can
# usage1 = ex.passthru.fun { name = 7; }; # result: { name = 7;} # - override attr values which have been supplied earlier
# usage2 = ex.passthru.fun (a: a // {name = __add a.name 1; }); # result: { a = 7; } # - use attr values before they have been supplied by accessing the fix point
# fix usage: # name "fixed"
# usage3a = ex.passthru.fun (a: a // {name2 = a.fixed.toBePassed; }); # usage3a will fail because toBePassed is not yet given # f: the (delayed overridden) arguments are applied to this
# usage3b usage3a.passthru.fun { toBePassed = "foo";}; # result { name = 7; name2 = "foo"; toBePassed = "foo"; fixed = <this attrs>; } #
applyAndFun = f : merge : x : assert (__isAttrs x || __isFunction x); # initial: initial attrs arguments and settings. see defaultOverridableDelayableArgs
let takeFix = if (__isFunction x) then x else (attr: merge attr x); in #
setAttrMerge "passthru" {} (lib.fix (fixed : f (takeFix {inherit fixed;}))) # returns: f applied to the arguments // special attributes attrs
( y : y // # a) merge: merge applied args with new args. Wether an argument is overridden depends on the merge settings
{ # b) replace: this let's you replace and remove names no matter which merge function has been set
fun = z : applyAndFun f merge (fixed: merge (takeFix fixed) z); #
funMerge = z : applyAndFun f merge (fixed: let e = takeFix fixed; in merge e (merge e z)); # examples: see test cases "res" below;
} ); overridableDelayableArgs =
mergeOrApply = merge : x : y : if (__isFunction y) then y x else merge x y; f : # the function applied to the arguments
initial : # you pass attrs, the functions below are passing a function taking the fix argument
let
takeFixed = if (__isFunction initial) then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
tidy = args :
let # apply all functions given in "applyPreTidy" in sequence
applyPreTidyFun = fold ( n : a : x : n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args);
in removeAttrs (applyPreTidyFun args) ( ["applyPreTidy"] ++ (maybeAttr "removeAttrs" [] args) ); # tidy up args before applying them
fun = n : x :
let newArgs = fixed :
let args = takeFixed fixed;
mergeFun = __getAttr n args;
in if __isAttrs x then (mergeFun args x)
else assert __isFunction x;
mergeFun args (x ( args // { inherit fixed; }));
in overridableDelayableArgs f newArgs;
in
(f (tidy (lib.fix takeFixed))) // {
merge = fun "mergeFun";
replace = fun "keepFun";
};
defaultOverridableDelayableArgs = f :
let defaults = {
mergeFun = mergeAttrByFunc; # default merge function. merge strategie (concatenate lists, strings) is given by mergeAttrBy
keepFun = a : b : { inherit (a) removeAttrs mergeFun keepFun mergeAttrBy; } // b; # even when using replace preserve these values
applyPreTidy = []; # list of functions applied to args before args are tidied up (usage case : prepareDerivationArgs)
mergeAttrBy = mergeAttrBy // {
applyPreTidy = a : b : a ++ b;
removeAttrs = a : b: a ++ b;
};
removeAttrs = ["mergeFun" "keepFun" "mergeAttrBy" "removeAttrs" "fixed" ]; # before applying the arguments to the function make sure these names are gone
};
in (overridableDelayableArgs f defaults).merge;
# rec { # an example of how composedArgsAndFun can be used # rec { # an example of how composedArgsAndFun can be used
# a = composedArgsAndFun (x : x) { a = ["2"]; meta = { d = "bar";}; }; # a = composedArgsAndFun (x : x) { a = ["2"]; meta = { d = "bar";}; };
@ -293,7 +327,7 @@ rec {
# }; # };
# will result in # will result in
# { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; } # { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
# is used by prepareDerivationArgs and can be used when composing using # is used by prepareDerivationArgs, defaultOverridableDelayableArgs and can be used when composing using
# foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix # foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
mergeAttrByFunc = x : y : mergeAttrByFunc = x : y :
let let
@ -364,6 +398,7 @@ rec {
# heavily in the new python and libs implementation # heavily in the new python and libs implementation
# #
# should we check for misspelled cfg options? # should we check for misspelled cfg options?
# TODO use args.mergeFun here as well?
prepareDerivationArgs = args: prepareDerivationArgs = args:
let args2 = { cfg = {}; flags = {}; } // args; let args2 = { cfg = {}; flags = {}; } // args;
flagName = name : "${name}Support"; flagName = name : "${name}Support";
@ -379,7 +414,7 @@ rec {
) args2.flags ); ) args2.flags );
in removeAttrs in removeAttrs
(mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }])) (mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }]))
["flags" "cfg" "mergeAttrBy" "fixed" ]; # fixed may be passed as fix argument or such ["flags" "cfg" "mergeAttrBy" ];
# deep, strict equality testing. This should be implemented as primop # deep, strict equality testing. This should be implemented as primop
@ -395,4 +430,3 @@ rec {
&& (eqListStrict (lib.attrValues a) (lib.attrValues b)) && (eqListStrict (lib.attrValues a) (lib.attrValues b))
else a == b; # FIXME ! else a == b; # FIXME !
} }