Skip to content

Instantly share code, notes, and snippets.

@ghadishayban
Created November 6, 2014 03:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ghadishayban/ed64040c9c7de4b4663c to your computer and use it in GitHub Desktop.
Save ghadishayban/ed64040c9c7de4b4663c to your computer and use it in GitHub Desktop.
Transducers <3 Iterators
(import clojure.lang.RT)
(defn iterator [xfn iter]
(XFIterator. xfn (RT/iter iter))) ;; clojure 1.7.0-alpha3 for RT/iter
import clojure.lang.RT;
import clojure.lang.IFn;
import clojure.lang.AFn;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.NoSuchElementException;
public class XFIterator implements Iterator {
static IFn append = new AFn(){
public Object invoke(Object result){
return result;
}
public Object invoke(Object result, Object input){
XFIterator i = (XFIterator) result;
i.buf.add(input);
return i;
}
};
private final IFn xform;
private Iterator iter;
private final ArrayList buf;
private int pos = 0;
public XFIterator (IFn xform, Iterator iter) {
this.iter = iter;
this.buf = new ArrayList();
this.xform = (IFn) xform.invoke(append);
}
public boolean hasNext() {
if (remaining())
return true;
pull();
return remaining();
}
private boolean remaining() {
if (pos < buf.size())
return true;
return false;
}
private Object bufNext() {
Object ret = buf.get(pos);
pos++;
if (pos == buf.size()) {
buf.clear();
pos = 0;
}
return ret;
}
public Object next() {
if (remaining()) {
return bufNext();
}
pull();
if (remaining()) {
return bufNext();
}
throw new NoSuchElementException();
}
private void pull() {
if (iter == null)
return;
while (buf.size() == 0) {
if(iter.hasNext()) {
if(RT.isReduced(xform.invoke(this, iter.next()))) {
iter = null;
xform.invoke(this);
return;
}
} else {
iter = null;
xform.invoke(this);
return;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment