A channel-chatter feladatban már használtál streameket, a boatswains-bilge-ben pedig meg is szabadultál tőlük. Ez a feladat az első saját streamod: egy osztály, amely megvalósítja a protokollt, így ugyanaz a with-input-stream / read1 / stream-read1 kód, amely egy <string-reader>-en működött, a te streameden is működni fog.
A TUPLE: child < parent … szerkezetet már ismered a dragons-descendants feladatból: ez egy egyetlen szülős hierarchia, ahol a slotok lefelé öröklődnek. A Factorban van egy második mód is az osztálygráf bővítésére: a nyílt mixinek. A MIXIN: m egy olyan osztályt deklarál, amelynek nincsenek slotjai, és amelyhez más osztályok utólag csatlakozhatnak az INSTANCE: c m segítségével. A tagság több-a-többhöz jellegű: egy osztály annyi mixin példánya lehet, amennyi csak tetszik.
A streamek protokollja két mixinnel jelöli, hogy az interfész melyik felét valósítja meg egy osztály:
INSTANCE: my-stream input-stream ! readable
INSTANCE: my-stream output-stream ! writable
Egy stream lehet az egyik, a másik, vagy mindkettő. Az input-stream (vagy output-stream) generikus metódusai ezután minden olyan osztályra elirányítanak, amely csatlakozott a mixinhez. Így találnak el a környezeti read1, stream-contents, with-input-stream stb. a te osztályodig.
A mixinek nyíltak: a mixin deklarálása után is hozzáadhatsz új tagot, akár egy másik szótárban is. Ez a különbség a TUPLE: < parent-hez képest, ahol a kapcsolat már a gyermekosztály deklarálásakor rögzül.
A protokoll generikusai az io szótárban találhatók:
stream-read1 ( stream -- elt/f )
stream-read ( n stream -- seq/f )
stream-read-unsafe ( n buf stream -- count )
stream-write1 ( elt stream -- )
stream-write ( seq stream -- )
stream-flush ( stream -- )
stream-element-type ( stream -- type )
A stream-read1 visszaadja a következő bájtot (vagy f-et a stream végén); a stream-write1 pedig egyet ír. A stream-read-unsafe az alacsonyabb szintű kötegelt olvasás, amelyet a legtöbb bemeneti stream biztosít; a stream-read erre épül, és kezeli a memóriafoglalást. A stream-element-type megmondja, hogy a stream bájtokkal (+byte+) vagy karakterekkel (+character+) dolgozik-e; amikor egy másik streamet csomagolsz be, a legegyszerűbb megvalósítás egyszerűen továbbadja a hívást a mögöttesnek.
destructors-ból jönA streamek disposable objektumok: egy saját stream kiterjeszti a disposable-t, és megvalósítja a dispose*-ot. Ez a boatswains-bilge-ből ismert keretrendszer, most egy streamosztályra alkalmazva:
TUPLE: my-stream < disposable underlying ;
: <my-stream> ( underlying -- s )
my-stream new-disposable swap >>underlying ;
M: my-stream dispose* underlying>> dispose ;
Ha ez megvan, a channel-chatter-ből ismert összes with-… kombinátor automatikusan működik a te streameden.
Rádiótávírász vagy egy teherhajón. A jel egy zajos vonalon fut be, hajógépek zaja, időjárási statikus zaj, néha idegen beszéd keveredik bele, mindez összekeveredve azzal a Morse-jelet, amit figyelsz. Az üzenet elkapásához a vezetéket átvezeted egy tape eszközön, amely mindent kiszűr, kivéve az érvényes Morse-szimbólumokat (., -, és a betűket elválasztó szóközt).
A feladatod, hogy a tape-et egy saját Factor bemeneti streamként építsd meg.
Definiálj egy tape tuple-t, amely kiterjeszti a disposable-t, és egyetlen slotot, a wire-t tartalmazza a mögöttes bemeneti stream számára.
TUPLE: tape < disposable wire ;
Ezután írd meg a <tape> ( wire -- tape ) konstruktort. A new-disposable-t használd (ne a new-t), hogy a destruktor-keretrendszer regisztrálja a tape-et, és a mögöttes streamet a wire slotban tárold.
Jelentsd ki, hogy a tape egy input-stream:
INSTANCE: tape input-stream
Ezzel a protokoll alapértelmezett kombinátorai a te osztályodra irányítják a hívást.
Valósítsd meg a M: tape stream-read1 ( tape -- elt/f ) metódust. Olvass bájtokat a mögöttes wire-ból, amíg rá nem találsz a CHAR: ., CHAR: - vagy CHAR: \s (szóköz) egyikére. Add vissza ezt a bájtot. Ha a wire f-et ad vissza (a stream vége), akkor te is adj vissza f-et: a tape ezzel végzett.
"x.y -ab cz" <string-reader> <tape>
[ stream-read1 ] [ stream-read1 ] [ stream-read1 ] tri
! => CHAR: . CHAR: - CHAR: \s
A M: tape stream-element-type ( tape -- type ) metódust úgy valósítsd meg, hogy a wire-ra delegálsz: a tape nem változtatja meg a beolvasott elemek fajtáját.
Valósítsd meg a M: tape dispose* ( tape -- ) metódust. A keretrendszer minden dispose hívásnál pontosan egyszer hívja meg a metódusodat; egyszerűen csak a mögöttes wire-t szabadítsd fel.
Ha ez az öt elem a helyén van, a tape szabályos bemeneti streamként működik: a with-input-stream, a stream-read és a többi protokollszó automatikusan a te metódusaidra irányítja a hívást.
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Factor nyelvet 47 fogalom163 feladat segítségével, valódi emberi mentorálással, mindez ingyen.