1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
/** -*-C-*-ish
Kaya standard library
Copyright (C) 2004, 2005 Edwin Brady
This file is distributed under the terms of the GNU Lesser General
Public Licence. See COPYING for licence.
*/
module LazyArray;
import Prelude;
"Lazy Arrays of element type <em>val</em>."
// init is the initial state, used for a reset.
abstract data LazyArray<state,val>(state init, state current,
(state,val)(state) next, Bool(state) end,
Void(state) cleanup,
Void(state) reset);
Exception EndOfArray = Exception("Reached the end of the Array",140);
"Default Array cleanup function."
public Void defaultCleanup(state s)
{
// Do nothing
}
"Default Array reset function."
public Void defaultReset(state s)
{
// Do nothing
}
"Create a lazy Array.
<em>state</em> is the type holding the state which is used to generate
the next item. <em>next</em> returns the next item and modifies state.
<em>end</em> is the termination test; use <em>Infinite</em> for no
termination."
public LazyArray<state,val> lazyArray(state st,
(state,val)(state) next,
Bool(state) end = Infinite,
Void(state) cleanup = defaultCleanup,
Void(state) reset = defaultReset)
{
return LazyArray(st,st,next,end,cleanup,reset);
}
"Reset the state of a lazy Array to the initial state."
public Void reset(var LazyArray<state,val> list)
{
f = list.reset;
f(list.current);
list.current = list.init;
}
"Get the next element in a lazy list."
public val getNext(var LazyArray<state,val> gen) {
if (end(gen)) {
throw(EndOfArray);
}
p = gen.next(gen.current);
gen.current = p.fst;
return p.snd;
}
"Termination test for infinite lazy Arrays."
public Bool Infinite(a foo) = false;
"Check whether we have reached the end of a Array."
public Bool end(LazyArray<state,val> gen) {
if (gen.end(gen.current)) {
f = gen.cleanup;
f(gen.current);
return true;
}
return false;
}
"Turn a lazy Array into a real Array."
public [val] makeArray(LazyArray<state,val> gen) {
list = [];
reset(gen);
while(!end(gen)) {
push(list,getNext(gen));
}
return list;
}
"Generate a list of numbers lazily."
public LazyArray<Int,Int> lazyRange(Int start, Int end, Int step)
{
return lazyArray(start-step,
lambda(x) { return (x+step, x+step); },
lambda(x) { if (step>0) { return (x+step)>end; }
else { return (x+step)<end; }
}
);
}
"Map across an array lazily."
public LazyArray<Int,b> mapLazily(b(a) f, [a] xs) {
return lazyArray(0,
lambda(x) { x++; return (x,f(xs[x-1])); },
lambda(x) -> { x==size(xs) });
}
"Map across a lazy array lazily."
public
LazyArray<LazyArray<state,a>,b> lazyMap(b(a) f, LazyArray<state,a> xs) {
reset(xs);
return lazyArray(xs,
lambda(x) -> { f(getNext(x)) },
end);
}
|