//import collections.LazyVector;
/**
* Boolean not operator.
*/
<Any T> boolean not(boolean b) = !b;
/**
*
*/
<Any T, Any U> U maybe(U defaultValue, T->U xform, ?T maybeItem) {
if (maybeItem == null) {
return defaultValue;
} else {
return xform(cast(maybeItem));
}
}
/**
* Returns the first element of a 2-tuple.
*/
<Any T, Any U> T fst((T,U) tup) {
(T t, U u) = tup;
return t;
}
/**
* Returns the second element of a 2-tuple.
*/
<Any T, Any U> U snd((T, U) tup) {
(T t, U u) = tup;
return u;
}
/**
* Returns the first element of a 3-tuple.
*/
<Any T, Any U, Any V> T fst3((T, U, V) tup) {
(T t, U u, V v) = tup;
return t;
}
/**
* Returns the second element of a 3-tuple.
*/
<Any T, Any U, Any V> U snd3((T, U, V) tup) {
(T t, U u, V v) = tup;
return u;
}
/**
* Returns the third element of a 3-tuple.
*/
<Any T, Any U, Any V> V thrd((T, U, V) tup) {
(T t, U u, V v) = tup;
return v;
}
/**
* Given a function <tt>func</tt>, which takes two arguments, return a function
* which takes one argument, and returns another function which takes an argument
* and returns the final result. An example is probably clearer:
*
* * var (int,int)->int addInts = (int x, int y) => {
* return x + y;
* };
* println(addInts(5,6));
*
* var int->int->int curriedAddInts = curry(addInts);
* var addFive = curriedAddInts(5);
* println(addFive(6));
* </pre>
*
* prints "11" twice.
*
* @see uncurry
* @see flip
*/
<Any T, Any U, Any V> T->U->V curry((T,U)->V func) = T parm1 => U parm2 => func(parm1, parm2);
/**
* Given a curried function func (see the <tt>curry</tt> function), return a function
* which takes two arguments, the opposite of <tt>curry</tt>.
*
* @see curry
* @see flip
*/
<Any T, Any U, Any V> (T,U)->V uncurry(T->U->V func) = (T parm1, U parm2) => func(parm1)(parm2);
//<Any T> T id(T t) = t;
/**
* Function composition. Given functions f2 and f1, return a function which takes the same
* argument f1 did, and returns the same thing f2 did. That is, <tt>compose(f2, f1)</tt>
* returns a function which is equivalent to <tt>f2(f1(x))</tt>.
*/
<Any T, Any U, Any V> T->V compose(U->V f2, T->U f1) = T parm => f2(f1(parm));
/**
* Reverses argument order for a curried function.
*/
<Any T, Any U, Any V> U->T->V flip(T->U->V func) = U parm2 => T parm1 => func(parm1)(parm2);
/**
* Reverses argument order for a normal function with two parameters.
*/
<Any T, Any U, Any V> (U, T)->V flipT((T,U)->V func) = (U parm2, T parm1) => func(parm1, parm2);
/**
* Repeatedly applies <tt>xform</tt> to its own result, using <tt>item</tt> as a starting
* value, until <tt>check</tt> returns true, then returns the last result from <tt>xform</tt>.
*/
<Any T> T until(T->boolean check, T->T xform, T item) {
while(!check(item)) {
item = xform(item);
}
return item;
}
/**
* Throw a runtime exception.
* @param msg=Error message
*
*/
void exception(String msg) {
throw new RuntimeException(msg);
}
<Any A, Any B> Sequence<A> scanLeft(Sequence<B> seq, (A,B)->A func, A start);
scanLeft<A,B>(seq@Sequence, func, start) {
Vector<A> vec = makeVector(size(seq));
vec.add(start);
A last = start;
B next;
for(int i = 0; i < size(seq); i++) {
next = seq[i];
last = func(last, next);
vec.add(last);
}
return vec;
}
scanLeft<A,B>(seq@LazyVector, func, start) {
int counter = 0;
A last = start;
return makeLV(()=>{
last = func(last, seq[counter]);
counter++;
return start;
});
}
<Any A> Sequence<A> scanLeft1(Sequence<A> seq, (A,A)->A func );
scanLeft1<A>(seq@Sequence, func) {
Vector<A> vec = makeVector(size(seq));
vec.add(seq[0]);
A last = seq[0];
A next;
for(int i = 1; i < size(seq); i++) {
next = seq[i];
last = func(last, next);
vec.add(last);
}
return vec;
}
scanLeft1<A>(seq@LazyVector, func) {
int counter = 0;
A start = cast(null); //We will definitely initialize this variable before
//actually using it, but not sure how to prove this to
//the compiler.
return makeLV(()=> {
if (counter == 0) {
start = seq[0];
counter++;
}
start = func(start, seq[counter]);
counter++;
return start;
});
}
<Any A> A foldLeft1(Sequence<A> seq, (A, A)->A func) {
A result = seq[0];
//Avoid asking for size() because it might (like for linked lists)
//be expensive to do so, and we don't actually need it for a left
//fold.
try {
for(int i = 1;; i++) {
result = func(seq[i], result);
}
} catch (ArrayIndexOutOfBoundsException e) {
//Walked off end of seq, not an error
}
return result;
}
<Any A, Any B> B foldRight((A, B)->B func, B start, Sequence<A> seq) {
B result = start;
for(int i = size(seq) - 1; i >= 0; i--) {
result = func(seq[i], start);
}
return result;
}
<Any A> A foldRight1(Sequence<A> seq, (A, A)->A func) {
A result = seq[size(seq) - 1];
for(int i = size(seq) - 2; i >= 0; i--) {
result = func(seq[i], result);
}
return result;
}
<Any A, Any B> Sequence<B> scanRight(Sequence<A> seq, (A,B)->B func, B start) {
Vector<B> vec = makeVector(size(seq));
vec.add(start);
B last = start;
for(int i = size(seq) - 1; i >= 0; i--) {
vec.add(func(seq[i], last));
}
return vec;
}
<Any A> Sequence<A> scanRight1(Sequence<A> seq, (A,A)->A func, A start) {
Vector<A> vec = makeVector(size(seq));
vec.add(start);
A last = seq[size(seq) - 1];
for(int i = size(seq) - 2; i >= 0; i--) {
vec.add(func(seq[i], last));
}
return vec;
}
<Any A> LazyVector<A> iterate(A->A func, A start) {
LazyVector<A> vec = makeLV(() => {
start = func(start);
return start;
});
vec.elements[0] = start;
vec.length = 1;
return vec;
}
<Any A> LazyVector<A> repeat(A item) = makeLV(() => item);
<Any A> Sequence<A> replicate(int number, A item) = repeat(item).take(number);
<Any A> LazyVector<A> cycle(Sequence<A> seq) {
int currentIndex = 0;
return makeLV(() => {
if (size(seq) <= currentIndex) {
currentIndex = 0;
}
A item = seq[currentIndex];
currentIndex++;
return item;
});
}
<Any A> Sequence<A> take(Sequence<A> seq, int number);
take<A>(seq@Sequence, number) {
if (number <= 0) {
return makeVector(0);
} else {
Vector<A> vec = makeVector(number);
int maxLen = min(number, size(seq));
for(int i = 0; i < maxLen; i++) {
vec.add(seq[i]);
}
return vec;
}
}
take<A>(seq@LazyVector, number) = makeLV(()=> seq[number++]);
<Any A> Sequence<A> drop(Sequence<A> seq, int number);
drop<A>(seq@Sequence, number) {
if (number <= 0) {
return new Vector(elements: toArray(seq), length: seq.size());
}
if (seq.size() < number) {
return makeVector(0);
}
Vector<A> vec = makeVector(seq.size() - number);
while(true) {
try {
vec.add(seq[number]);
number++;
} catch (Exception e) {
break;
}
}
return vec;
}
drop<A>(seq@LazyVector, number) = makeLV(() => seq[number++]);
<Any A> (Sequence<A>, Sequence<A>) splitAt(Sequence<A> seq, int index);
splitAt<A>(seq@Sequence, index) {
Vector<A> first = makeVector(index);
Vector<A> second = makeVector(10);
for(int i = 0;; i++) {
try {
if (i < index)
first.add(seq[i]);
else
second.add(seq[i]);
} catch (Exception e) {
//Nothing...
}
}
return (first, second);
}
<Any T> Sequence<T> takeWhile(Sequence<T> seq, T->boolean test) {
Vector<T> vec = makeVector(10);
seq.find(T item => {
boolean res = true;
if (test(item)) {
vec.add(item);
res = false;
}
return res;
});
return vec;
}
<Any T> void eachUntil(Sequence<T> seq, T->boolean test, T->void func) {
try {
for(int i = 0; test(seq[i]); i++) {
func(seq[i]);
}
} catch (ArrayIndexOutOfBoundsException e) {
//nothing
}
}
<Any T> void eachFrom(Sequence<T> seq, T->boolean test, T->void func) {
try {
int i = 0;
for(;!test(seq[i]);i++) {}
for(;; i++) {
func(seq[i]);
}
} catch (ArrayIndexOutOfBoundsException e) {
//nothing
}
}
<Any T> Sequence<T> dropWhile(Sequence<T> seq, T->boolean test) {
Vector<T> vec = makeVector(10);
int len = size(seq);
boolean failed = false;
for(int i = 0; i < len; i++) {
if (failed) {
vec.add(seq[i]);
} else if (test(seq[i])) {
failed = true;
vec.add(seq[i]);
}
}
return vec;
}
<Any T> (Sequence<T>, Sequence<T>) span(Sequence<T> seq, T->boolean test) = (seq.takeWhile(test), seq.dropWhile(test));
<Any T> (Sequence<T>, Sequence<T>) brk(Sequence<T> seq, T->boolean test) = seq.span(compose(not, test));
Vector<String> lines(String s) {
java.util.StringTokenizer strtok = new java.util.StringTokenizer(s, "\n");
return makeLV(() => {
if (!strtok.hasMoreTokens()) {
indexError();
}
//return notNull(strtok.nextToken());
return cast(strtok.nextToken());
});
}
//TODO: accept other whitespace than " ", like the Haskell function does.
Vector<String> words(String s) {
java.util.StringTokenizer strtok = new java.util.StringTokenizer(s, " ");
return makeLV(() => {
if (!strtok.hasMoreTokens()) {
indexError();
}
//return notNull(strtok.nextToken());
return cast(strtok.nextToken());
});
}
String unlines(Sequence<String> seq) = seq.map(String s => s + "\n").foldLeft1(concat);
String unwords(Sequence<String> seq) = seq.map(String s => s + " ").foldLeft1(concat);
<Any A> Sequence<A> reverse(Sequence<A> seq) {
int seqSize = size(seq);
Vector<A> vec = makeVector(seqSize);
for(int i = seqSize - 1; i >= 0; i--) {
vec.add(seq[i]);
}
return vec;
}
boolean and(Sequence<boolean> seq) {
for(int i = 0; i < seq.size(); i++) {
if (!seq[i])
return false;
}
return true;
}
//or is defined in prelude.nice
<Any T>boolean all(Sequence<T> seq, T->boolean test) {
//or we could use: and(seq.map(test));
for(int i = 0; i < seq.size(); i++) {
if (!test(seq[i]))
return false;
}
return true;
}
//any is equivalent to prelude.nice.has().
<Any T>boolean elem(Sequence<T> seq, T item) = seq.has(T each => each.equals(item));
<Any T>boolean notElem(Sequence<T> seq, T item) = seq.has(T each => !each.equals(item));
<Any T, Any U> ?U lookup(Sequence<(T,!U)> seq, T key) {
for(int i = 0; i < seq.size(); i++) {
(T k, !U value) = seq[i];
if (equals(k, key))
return value;
}
return null;
}
//Needed for sum and product
// Number plus(Number one, Number two) = one + two;
// Number mult(Number one, Number two) = one * two;
// <Number T> T sum(Sequence<T> seq) = seq.foldLeft(plus, 0);
// <Number T> T product(Sequence<T> seq) = seq.foldLeft(mult, 1);
long min(Sequence<long> s) {
long res=0;
for(int i=0; i<s.size(); i++)
if(s.get(i)<res)
res=s.get(i);
return res;
}
//maximum and minimum are max and min in Nice.
//String isn't a Sequence, so this could be tricky...
//<Collection C, Any T, Any U> Sequence<U> concatMap(C<T> coll, T->U xform) = concat(coll.map(xform));
<Any T, Any U> Sequence<(T,U)> zip(Sequence<T> tSeq, Sequence<U> uSeq) = zipWith((T t, U u) => (t, u), tSeq, uSeq);
<Any T, Any U, Any V> Sequence<(T,U,V)> zip3(Sequence<T> tSeq, Sequence<U> uSeq, Sequence<V> vSeq) =
zipWith3((T t, U u, V v) => (t, u, v), tSeq, uSeq, vSeq);
<Any T, Any U, Any V> Sequence<V> zipWith((T,U)->V func, Sequence<T> tSeq, Sequence<U> uSeq) {
int minLen = min(size(tSeq), size(uSeq));
Vector<V> vec = makeVector(minLen);
for(int i = 0; i < minLen; i++) {
vec.add(func(tSeq[i], uSeq[i]));
}
return vec;
}
<Any T, Any U, Any V, Any W> Sequence<W> zipWith3((T,U,V)->W func, Sequence<T> tSeq, Sequence<U> uSeq, Sequence<V> vSeq) {
int minLen = min(size(tSeq), size(uSeq));
Vector<W> vec = makeVector(minLen);
for(int i = 0; i < minLen; i++) {
vec.add(func(tSeq[i], uSeq[i], vSeq[i]));
}
return vec;
}
<Any T, Any U> (Sequence<T>, Sequence<U>) unzip(Sequence<(T,U)> seq) {
Vector<T> tVec = makeVector(size(seq));
Vector<U> uVec = makeVector(size(seq));
seq.foreach((T,U) tup => {
tVec.add(fst(tup));
uVec.add(snd(tup));
});
return (tVec, uVec);
}
<Any T, Any U, Any V> (Sequence<T>, Sequence<U>, Sequence<V>) unzip3(Sequence<(T,U,V)> seq) {
int len = size(seq);
Vector<T> tVec = makeVector(len);
Vector<U> uVec = makeVector(len);
Vector<V> vVec = makeVector(len);
seq.foreach((T,U,V) tup => {
tVec.add(fst3(tup));
uVec.add(snd3(tup));
vVec.add(thrd(tup));
});
return (tVec, uVec, vVec);
}
| Topic HaskellPreludeExample . { Edit | Attach | Ref-By | Printable | Diffs | r1.1 | More } |
|
Revision r1.1 - 30 Jan 2003 - 00:07 GMT - TWikiGuest Parents: WebHome > CodeExamples |
Copyright © 1999-2003 by the contributing authors.
All material on this collaboration platform is the property of the contributing authors. Ideas, requests, problems regarding TWiki? Send feedback. |