org.abora.gold.collection.steppers
Class Stepper

java.lang.Object
  |
  +--org.abora.gold.java.AboraHeaper
        |
        +--org.abora.gold.xpp.basic.Heaper
              |
              +--org.abora.gold.collection.steppers.Stepper
Direct Known Subclasses:
AscendingIntegerStepper, BoxProjectionStepper, BoxStepper, DescendingIntegerStepper, DisjointRegionStepper, EdgeSimpleRegionStepper, EdgeStepper, EmptyStepper, GenericCrossSimpleRegionStepper, GrandDataPageStepper, GrandHashSetStepper, GrandNodeStepper, GrandOverflowStepper, HashSetStepper, IDSimpleStepper, IDStepper, IntegerEdgeStepper, IntegerSimpleRegionStepper, ItemStepper, MergeBundlesStepper, MergeStepper, PrimIndexTableStepper, PrimPtr2PtrTableStepper, PrimPtrTableStepper, PrimSetStepper, RealStepper, SequenceStepper, SetTableStepper, TableStepper, TupleStepper

public class Stepper
extends Heaper

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.xpp.basic.Heaper
abstractDeclarationFor, abstractTypeFor, addMethodAttributeToInOf, addPackage, addPackageCategory, allClientProtocolOn, argumentTypesFor, arrow, blast, blast, BLAST, cachePromiseNameTable, cachePromiseNameTableIn, canYouBecome, cast, cleanPromiseClasses, cleanupGarbage, clientClassesDo, clientFunctionsOn, clientMethodsOn, clientProtocol, clientProtocolDo, clientProtocolOn, clientProtocolOn, collectibleClasses, compare, compileClientSubclasses, compileConstantPromiseMethods, compileCreateFromRcvr, compileEQ, compileGeneratedClassMethod, compileGeneratedMethod, compileHook, compilePromise, compilePromiseDefaultMethods, compilePromiseFluidDeclarations, compilePromiseHandlers, compilePromiseMethods, compileRequestCreateMsgInArguments, compileRequestEvaluateMsgInReturningArguments, compileRPCSpecialistEvaluateMsgForReturningArguments, compileSendSelfTo, compileSendSelfToSendHook, compileStubbleMethods, compileSubclassStubbleMethods, computeMangle, computePreorder, constantTypeValue, convert, convertCopyDeclarations, convertDeferredDeclarations, convertProxyDeclarations, convertSubclassCopyDeclarations, convertSubclassDeferredDeclarations, convertSubclassProxyDeclarations, copyReferencesToType, create, create, create, create, create, create, create, create, create, create, createRequestClassArguments, definesProxyMethods, delete, deref, destroy, destruct, destructor, enum, enumFlags, equals, exportName, fetchAttribute, fetchPackage, fetchSuperCategory, fileOutClientProtocol, findCategory, findSenderAndReceiverMethods, findTailInto, flushPromiseNameTable, foo, freezeClientClasses, freezeClientProtocol, freezeStProtocol, frozenClasses, garbageCollect, garbageCollectFrom, gcOpportunity, gcOpportunity, generatedCategory, generatePromiseNames, getCategory, getOrMakePackage, getSuperCategory, handlerSignaturesFrom, hash, hashForEqual, hasProxyMethods, info_clientClasses, info_clientSideClasses, info_promiseClasses, info_stProtocol, inGC, initializedClasses, initializingClasses, initPackages, initStringHashSBoxes, inspectPieces, instanceSize, IntegerVar, isByProxy, isConstructed, isDestructed, isEqual, isEqualOrSubclassOf, isGenerated, isIntType, isKindOf, isRawType, isUnlocked, make, makeClassTable, makeFillTable, makeRequestTable, mangle, markChildren, markCount, markInstances, mayBecome, mayBecomeAnySubclassOf, new1, newX, nonCopyVariables, notWorking, pack, packageClasses, packagingCategory, parseExportName, passe, pointerToStaticMember, pointerToStaticMember, pointerToVirtualMember, preorderMax, preorderNumber, printOn, PROBLEM, problems, promiseClass, promiseDefaultValue, promiseName, promiseNameTable, promiseToAbstract, registerPackageCategory, removeGeneratedCode, removeStubbleMethods, removeSubclassGeneratedCode, removeSubclassStubbleMethods, requestProcedure, requestProceduresFrom, returnTypeFor, rootName, scheduleTermination, sendProxyTo, sendSelfTo, serverNameFor, setGC, signal, signals, smalltalkSelector, stClientProtocol, stubbleSelectorTokenReturnsArguments, subclassNonCopyVariables, takeOop, togglePromiseName, togglePromiseOfParse, unimplemented, unmangle, verifyFreeze, wipeStubble
 
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

TheEmptyStepper

protected static Stepper TheEmptyStepper
Constructor Detail

Stepper

public Stepper()
Method Detail

copy

public 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. Typically, this will mean that he
must produce the same future history that I'm going to produce. However, let's say that I
am enumerating the elements of a partial order in some full order which is consistent with
the partial order. If a copy of me is made after I'm part way through, then me and my copy
may produce any future history compatable both with the partial order and the elements
I've already produced by the time of the copy. Of course, a subclass or a Stepper creating
message (like IntegerRegion::stepper()) may specify the more stringent requirement (that a
copy must produce the same sequence).
To prevent aliasing, Steppers should typically be passed by copy. See class comment.


atEnd

public boolean atEnd()
Iff I have a current value (i.e. this message returns FALSE), then I am not exhasted.
'fetch' and 'get' will both return this value, and I can be 'step'ped to my next state. As
I am stepped, eventually I may become exhausted (the reverse of all the above), which is a
permanent condition.
Note that not all steppers have to be exhaustable. A Stepper which enumerates all primes
is perfectly reasonable. Assuming otherwise will create infinite loops. See class
comment.


fetch

public Heaper fetch()
If I am exhausted (i.e., if (!! this->hasValue())), then return NULL. Else return
current element. I return wimpily since most items returned are held by collections.
If I create a new object, I should cache it.


get

public Heaper get()
Essential. BLAST if exhasted. Else return current element. I return wimpily since most
items returned are held by collections. If I create a new object, I should cache it.


hasValue

public boolean hasValue()
Iff I have a current value (i.e. this message returns true), then I am not
exhasted. 'fetch' and 'get' will both return this value, and I can be 'step'ped to
my next state. As I am stepped, eventually I may become exhausted (the
reverse of all the above), which is a permanent condition.
Note that not all steppers have to be exhaustable. A Stepper which
enumerates all primes is perfectly reasonable. Assuming otherwise will create
infinite loops. See class comment.


step

public void step()
Essential. If I am currently exhausted (see Stepper::hasValue()), then it is an error to
step me. The result of doing so isn't currently specified (we probably should specify it
to BLAST, but I know that the implementation doesn't currently live up to that spec).
If I am not exhausted, then this advances me to my next state. If my current value (see
Stepper::get()) was my final value, then I am now exhausted, otherwise my new current
value is the next value.


stepMany

public PrimArray stepMany(int count)
Collects the remaining elements in the stepper into an array. Returns an array of no more
than count elements (or some arbitrary chunk if the count is negative). The fact that you
got fewer elements that you asked for does not mean that the stepper is atEnd, since there
may be some reason to break the result up into smaller chunks; you should always check.


theOne

public Heaper theOne()
If there is precisely one element in the stepper return it; if not, blast without changing
the state of the Stepper


forEach

public void forEach(BlockClosure fn)

stepMany

public PrimArray stepMany()

asArray

public PrimArray asArray(int count)

forEachPromise

public void forEachPromise(java.lang.Object aBlock)

actualHashForEqual

public int actualHashForEqual()
Overrides:
actualHashForEqual in class Heaper

isEqual

public boolean isEqual(java.lang.Object other)

emptyStepper

public static Stepper emptyStepper()
A Stepper which is born exhausted. Useful for implementing empty collections


itemStepper

public static Stepper itemStepper(Heaper item)
A Stepper which will enumerate only this one element. Useful for implementing
singleton collections.


initTimeNonInherited

public static void initTimeNonInherited()

linkTimeNonInherited

public static void linkTimeNonInherited()

info

public static void info()
{BooleanVar CLIENT} atEnd
{Heaper wimpy CLIENT} get
{void CLIENT} step
{PrimArray CLIENT} stepMany: count {Int32 default: -1}
{Heaper CLIENT} theOne



Translation - Copyright © 2003 David G Jones. All Rights Reserved.
Original Udanax-Gold - Copyright © 1979-1999 Udanax.com. All rights reserved.