diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2012-08-13 01:05:35 -0400 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2012-08-13 01:05:35 -0400 |
commit | b9e5b908ed29bfb6cd82837f9f57293c1f63e999 (patch) | |
tree | bf83e68c67ec3e37720634c6ccca1d53594a3346 /src | |
parent | 4ccd48ce2478cbe1263605838969f89d5b745f0a (diff) |
Provide an efficient implementation of ‘elem’
The one in Nixpkgs is O(n^2), this one is O(n). Big reduction in the
number of list allocations.
Statistics before (on a NixOS system config):
time elapsed: 1.17982
size of a value: 24
environments allocated: 1543334 (39624560 bytes)
list elements: 9612638 (76901104 bytes)
list concatenations: 37434
values allocated: 1854933 (44518392 bytes)
attribute sets allocated: 392040
right-biased unions: 186334
values copied in right-biased unions: 591137
symbols in symbol table: 18272
number of thunks: 1392467
number of thunks avoided: 1507311
number of attr lookups: 430801
number of primop calls: 691600
number of function calls: 1492502
Statistics after:
time elapsed: 1.08683
size of a value: 24
environments allocated: 1384376 (35809568 bytes)
list elements: 6946783 (55574264 bytes)
list concatenations: 37434
values allocated: 1760440 (42250560 bytes)
attribute sets allocated: 392040
right-biased unions: 186334
values copied in right-biased unions: 591137
symbols in symbol table: 18273
number of thunks: 1297673
number of thunks avoided: 1380759
number of attr lookups: 430802
number of primop calls: 628912
number of function calls: 1333544
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/primops.cc | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index db7aa9e89..aa27df6ad 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -880,7 +880,8 @@ static void prim_head(EvalState & state, Value * * args, Value & v) /* Return a list consisting of everything but the the first element of - a list. */ + a list. Warning: this function takes O(n) time, so you probably + don't want to use it! */ static void prim_tail(EvalState & state, Value * * args, Value & v) { state.forceList(*args[0]); @@ -930,6 +931,19 @@ static void prim_filter(EvalState & state, Value * * args, Value & v) } +static void prim_elem(EvalState & state, Value * * args, Value & v) +{ + bool res = false; + state.forceList(*args[1]); + for (unsigned int n = 0; n < args[1]->list.length; ++n) + if (state.eqValues(*args[0], *args[1]->list.elems[n])) { + res = true; + break; + } + mkBool(v, res); +} + + /* Return the length of a list. This is an O(1) time operation. */ static void prim_length(EvalState & state, Value * * args, Value & v) { @@ -1145,8 +1159,9 @@ void EvalState::createBaseEnv() addPrimOp("__tail", 1, prim_tail); addPrimOp("map", 2, prim_map); addPrimOp("__filter", 2, prim_filter); + addPrimOp("__elem", 2, prim_elem); addPrimOp("__length", 1, prim_length); - + // Integer arithmetic addPrimOp("__add", 2, prim_add); addPrimOp("__sub", 2, prim_sub); |