aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-08-13 01:05:35 -0400
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-08-13 01:05:35 -0400
commitb9e5b908ed29bfb6cd82837f9f57293c1f63e999 (patch)
treebf83e68c67ec3e37720634c6ccca1d53594a3346 /src
parent4ccd48ce2478cbe1263605838969f89d5b745f0a (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.cc19
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);