|
||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||
java.lang.Object
|
+--org.abora.gold.java.AboraHeaper
|
+--org.abora.gold.xpp.basic.Heaper
|
+--org.abora.gold.collection.steppers.Stepper
Steppers provide a common way to enumerate the elements of any abstraction which acts as a
collection. This simplifies the protocols of the various collection classes, as they now
merely have to provide messages to create the appropriate steppers, which then handle the
rest of the job. Also, the Stepper steps over the set of elements which existed *at the
time* the stepper was returned. If you''re stepping over the elements of a changable
collection, and the elements are changing while you are stepping, any other rule could
lead to confusion.
Smalltalk''s collections provide the protocol to enumerate their elements directly.
Having the collection change during stepping is the source of a famous Smalltalk bug. Clu
and Alphard both have "Iterators" which are much like our Steppers, but these other
languages both specify (as a pre-condition) that the collection not be changed while the
Iterator is active. This burdens the programmer with ensuring a non-local property that
we know of know way of robustly checking for in real programs.
Steppers and Accumulators are sort of duals. Steppers are typically used in loops as a
source of values to be consumed by the loop body. Accumulators are typically used as a
sink for values which are produced in the loop body. One can (and sometimes does)
interact with a Stepper explicitly through its protocol. However, for the typical case of
just executing a loop body in turn for each successive element should be written using the
FOR_EACH macro. The syntax of the macro is:
FOR_EACH(ElementType,varName, (stepperValuedExpr), {
Loop body (varName is in scope)
});
For example:
FOR_EACH(Position,each,(reg->stepper()), {
doSomethingWith (each);
});
is roughly equivalent to (see macro definition for exact equivalence):
for(SPTR(Stepper) stomp = reg->stepper(); stomp->hasValue(); stomp->step()) {
SPTR(Position) each = CAST(Position,stomp->fetch());
doSomethingWith (each);
}
stomp->destroy();
Since the Stepper is necessarily exhausted if we fall out the end of a FOR_EACH, and there
isn''t anything useful we can do with an exhausted stepper, it''s no great loss for
FOR_EACH to destroy it. Doing so substantially unburdens the garbage collector. In
addition, the means we are planning to use to lower the overhead of having the Stepper
step over a snapshot of the collection depends on (for its efficiency) the Stepper being
destroyed promptly if it is dropped without stepping it to exhaustion.
Not all Steppers will eventually terminate. For example, a Stepper which enumerates all
the primes is perfectly reasonable. When using Steppers (and especially FOR_EACH), you
should be confident that you haven''t just introduced an infinite loop into your program.
See Stepper::hasValue().
It is normally considered bad style for two methods/functions to be pointing at the same
Stepper. As long as Steppers are used locally and without aliasing (i.e., as if they were
pass-by-value Vars), these implementationally side-effecty objects can be understood
applicatively. If a copy of an Stepper can be passed instead of a pointer to the same
one, this is to be prefered. See Accumulator.
Subclasses of Stepper can provide more protocol. See TableStepper.
| Field Summary | |
protected static Stepper |
TheEmptyStepper
|
| Fields inherited from class org.abora.gold.xpp.basic.Heaper |
AllBlasts, BecomeMap, GarbageCount, InGC, InitializedClasses, InitializingClasses, LastMemory, NextClientRequestNumber, NotOneElementSignal, PackageTable, PromiseNameTable, StringHashSBoxes |
| Fields inherited from class org.abora.gold.java.AboraHeaper |
ActiveClubs, CurrentAuthor, CurrentBertCanopyCache, CurrentBertCrum, CurrentChunk, CurrentGrandMap, CurrentKeyMaster, CurrentPacker, CurrentSensorCanopyCache, CurrentServer, CurrentSession, CurrentSessions, CurrentTrace, InitialEditClub, InitialOwner, InitialReadClub, InitialSponsor, InsideTransactionFlag |
| Constructor Summary | |
Stepper()
|
|
| Method Summary | |
int |
actualHashForEqual()
|
PrimArray |
asArray(int count)
|
boolean |
atEnd()
Iff I have a current value (i.e. |
Stepper |
copy()
Return a new stepper which steps independently of me, but whose current value is the same as mine, and which must produce a future history of values which satisfies the same obligation that my contract obligates me to produce now. |
static Stepper |
emptyStepper()
A Stepper which is born exhausted. |
Heaper |
fetch()
If I am exhausted (i.e., if (!! this->hasValue())), then return NULL. |
void |
forEach(BlockClosure fn)
|
void |
forEachPromise(java.lang.Object aBlock)
|
Heaper |
get()
Essential. |
boolean |
hasValue()
Iff I have a current value (i.e. |
static void |
info()
{BooleanVar CLIENT} atEnd {Heaper wimpy CLIENT} get {void CLIENT} step {PrimArray CLIENT} stepMany: count {Int32 default: -1} {Heaper CLIENT} theOne |
static void |
initTimeNonInherited()
|
boolean |
isEqual(java.lang.Object other)
|
static Stepper |
itemStepper(Heaper item)
A Stepper which will enumerate only this one element. |
static void |
linkTimeNonInherited()
|
void |
step()
Essential. |
PrimArray |
stepMany()
|
PrimArray |
stepMany(int count)
Collects the remaining elements in the stepper into an array. |
Heaper |
theOne()
If there is precisely one element in the stepper return it; if not, blast without changing the state of the Stepper |
| Methods inherited from class org.abora.gold.java.AboraHeaper |
asOop, basicInspect, displayString, error, hack, halt, inspect, knownBug, mightNotImplement, REQUIRES, shouldImplement, shouldNotImplement, stubbleForSubclassResponsibility, thingToDo, willNotImplement |
| Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
protected static Stepper TheEmptyStepper
| Constructor Detail |
public Stepper()
| Method Detail |
public Stepper copy()
public boolean atEnd()
public Heaper fetch()
public Heaper get()
public boolean hasValue()
public void step()
public PrimArray stepMany(int count)
public Heaper theOne()
public void forEach(BlockClosure fn)
public PrimArray stepMany()
public PrimArray asArray(int count)
public void forEachPromise(java.lang.Object aBlock)
public int actualHashForEqual()
actualHashForEqual in class Heaperpublic boolean isEqual(java.lang.Object other)
public static Stepper emptyStepper()
public static Stepper itemStepper(Heaper item)
public static void initTimeNonInherited()
public static void linkTimeNonInherited()
public static void info()
|
||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||