forked from lix-project/lix
Add primop genList
This can be used to implement functions like ‘imap’ (or for that matter, ‘map’) without the quadratic complexity incurred by calling ‘++’ repeatedly.
This commit is contained in:
parent
f3dda728a4
commit
50807f3dd5
|
@ -364,6 +364,24 @@ builtins.fromJSON ''{"x": [1, 2, 3], "y": null}''
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry><term><function>builtins.genList</function>
|
||||||
|
<replaceable>generator</replaceable> <replaceable>length</replaceable></term>
|
||||||
|
|
||||||
|
<listitem><para>Generate list of size
|
||||||
|
<replaceable>length</replaceable>, with each element
|
||||||
|
<replaceable>i></replaceable> equal to the value returned by
|
||||||
|
<replaceable>generator</replaceable> <literal>i</literal>. For
|
||||||
|
example,
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
builtins.genList (x: x * x) 5
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
returns the list <literal>[ 0 1 4 9 16 ]</literal>.</para></listitem>
|
||||||
|
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
<varlistentry><term><function>builtins.getAttr</function>
|
<varlistentry><term><function>builtins.getAttr</function>
|
||||||
<replaceable>s</replaceable> <replaceable>set</replaceable></term>
|
<replaceable>s</replaceable> <replaceable>set</replaceable></term>
|
||||||
|
|
||||||
|
|
|
@ -1364,6 +1364,25 @@ static void prim_all(EvalState & state, const Pos & pos, Value * * args, Value &
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Apply a function to every element of a list. */
|
||||||
|
static void prim_genList(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
|
{
|
||||||
|
state.forceFunction(*args[0], pos);
|
||||||
|
auto len = state.forceInt(*args[1], pos);
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
throw EvalError(format("cannot create list of size %1%, at %2%") % len % pos);
|
||||||
|
|
||||||
|
state.mkList(v, len);
|
||||||
|
|
||||||
|
for (unsigned int n = 0; n < len; ++n) {
|
||||||
|
Value * arg = state.allocValue();
|
||||||
|
mkInt(*arg, n);
|
||||||
|
mkApp(*(v.listElems()[n] = state.allocValue()), *args[0], *arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Integer arithmetic
|
* Integer arithmetic
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
|
@ -1759,6 +1778,7 @@ void EvalState::createBaseEnv()
|
||||||
addPrimOp("__foldl'", 3, prim_foldlStrict);
|
addPrimOp("__foldl'", 3, prim_foldlStrict);
|
||||||
addPrimOp("__any", 2, prim_any);
|
addPrimOp("__any", 2, prim_any);
|
||||||
addPrimOp("__all", 2, prim_all);
|
addPrimOp("__all", 2, prim_all);
|
||||||
|
addPrimOp("__genList", 2, prim_genList);
|
||||||
|
|
||||||
// Integer arithmetic
|
// Integer arithmetic
|
||||||
addPrimOp("__add", 2, prim_add);
|
addPrimOp("__add", 2, prim_add);
|
||||||
|
|
|
@ -54,8 +54,8 @@ rec {
|
||||||
const = x: y: x;
|
const = x: y: x;
|
||||||
|
|
||||||
range = first: last:
|
range = first: last:
|
||||||
if builtins.lessThan last first
|
if first > last
|
||||||
then []
|
then []
|
||||||
else [first] ++ range (builtins.add first 1) last;
|
else genList (n: first + n) (last - first + 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue