Code: Select all
class enm extends itb { ;enumerator wrapper extends iterable
__New(ebl, enmw, atyx?) { ;instantiate w enum wrapper and arity transform
this.ebl := ebl ;enumerable subject
, this.enmw := enmw ;wrapper for __Enum(a)(p*)
, this.atyx := atyx ?? (x=>x) ;arity transform
}
__Enum(aty) ;enumeration start with arity
=> ((t:=this).aty := aty ;store arity in object
, t.enmw.call(t.ebl.__Enum(t.atyx.call(aty)))) ;call on wrapped fnc/arity
} ;=============================================================================
With this you can chain a bunch of stuff (like a Java stream, or lazy evaluation) such that the items pass through one at a time, rather than making intermediate lists. Like generators instead of list comprehensions for the Python gurus in the thread. If you also DefineProp the itb methods into Array.Prototype, the top of a for loop that uses this could look something like:
for i in myArray.drop(5).filter(x=>x>50).take(10).transform(x=>x*100)
where this drops the first 5 items, filters those above 50 but only the next 10 of them, multiplying each by 100. This is a crazy example, but it demonstrates the power and terse nature of chained enumerator functions.
The itb.take method looks like this, for example, so you can see how the constructor gets called:
Code: Select all
take(cnt) => enm(this ;enum take first count
, (i:=0, f => (p*) => (++i > cnt ? 0 : f(p*))))