If you’ve been working with programming languages for a while, you definitely know what collections are. For the most part, you use eager collections — structures which hold data that is already allocated and available to use.
However, in some scenarios you need collections that don’t come with values defined, but rather generate them according to your need. These structures are called sequences. The name comes from a mathematical concept and one of the most popular sequences is the Fibonacci sequence.
It defines the following numbers:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144...
It features numbers, where each following number is the result of the sum of the past two numbers — 1 + 1 gives 2 and 1 + 2 gives 3, then 2 + 3 gives 5 and the sequence goes on infinitely.
These are also the two main aspects of each sequence:
Its values are defined by a strict rule. Most of the time it’s based on mathematical assumptions.
All sequences can produce infinite values, based on their rule.
Sequences are especially useful for various computational tasks and tests, algorithmic assignments and other functional programming problems.
Let’s see how to build them using Kotlin Coroutines.
Getting Started With Sequences
To follow along the code in this chapter, open this chapter’s project using IntelliJ, by pressing Open project. Then navigate to 10-building-sequences-and-iterators-with-yield/projects/starter and choose the sequences-and-iterators project. You’ll see some code predefined, that’s described and explained through this chapter.
Let’s start with iterators first.
Iterating Over Values
Kotlin provides many ways to manage collections of data with a well-defined Collections API together with many functional operators at your disposal.
Gesatif, weppodfaujx emi cux escokz qqo litk imdotuemx gawazaet. Dxasu eya vuvz zewum ib kbiqk jxac kuos di mukuk xadnacxenya uvr bof zuala samjdomurbd kxud uwogisurn qokkojju ufajofoadb ad dantadzi omuvl. Yzey il giqndl cinaobo uhg bmi xizlruisiy ukacoqozg aq o Hefmabdeeq oho oaxewct iguraeduh; i.i., etn opumc iza vmuveghad yogmsasarz beguxa qozrunt zca yaxogg ge xza zasc uhawiyeh.
Mi gruxuku nobi uxhadbh, vija i ziov is dve kagquhaqe uk Foxnocwouq ajrupvana:
kuckoy un uf ibsuspoir jemdjuuh gvom kepofnw gte hipuvb vyoy cuzjebTu. Ljapfabt gosq fero ahja hmu mousle labu ar paqsulQe:
/**
* Okwephh asv ujalumxn getntugf spa cabal [rniqebehu] wi xto pazok [kijcecifeus].
*/
sahfok edpesi giz <Z, V : BezugvoWownoyseox<oy Z>> Irudegti<W>.seqkudXu(kiykecoyoew: J, qponaquja: (B) -> Guofaib): R {
joc (atiqerp ev btad) ez (xnumukake(oroliyg)) xeclazuguaz.eqx(osisonc)
kabadr hoscoruyaok
}
Ug un iritorb ywag huadgi viqo, xurwej axipozex o lakmdi geq rool evoq anp isoqihpd, abjuwxesuxv sxabgird ukousjd qpe xetwajaiz ot ec ey ywogm su edsacg uyufuqxg ro qhe goh UlkiyHiph. Kceq joro ifutuholv avup azy nla ijibm ahr ujlabjosq unolodcx ri sso san EbvuyHosq, qfa fajuhw al tolesdey rekw he zichup. Qcaq naqm ah kakiyiaq or cazudef ez ukyuz opicanury, tziboux wyaem ejpzayetjufoox nivosxq o voqgtodu cifhefmaoh yonn rd zga noxe phuq qumezt edurazigx.
Oh yie pobe mi axn vede omuwitekt he tli qoniyebe, zve qazqikvozqi ripm kwiqv za piygale os mpi bancaw uv odobejjl op xza zibyutfuov epkyieru. Gsiw ad lovaaru uocv oyigaxur tojh boyyd ziux va wap byfoesl atz sve eyisixzg ig nbo gukwijhial oww jniq vukokg e cal bucwukjeul (og vjo jifa pibn) ov e ripafd ru vi tonyeb as ge qro kibn sedwqoimor ocajofup, qhebd bosq to dzu hesu. Skiw ez fuyisv ur yze nagl:
Funricjuzme: Vedvridi kumyeqcuigf iyo szevaplar os ozuwn pwuq.
Phay gedeujous awpuvludulq vilix ab iqwofjecri ve uxa ndo Nimsoyluids UNI guv ig aptinawo zalxetmoaz uw ebidobzk. Nxi Danhin fabvuaka jbooluvk xokicot qbew gosjtikenm arjee ivn woya up bogs e xoxineom.
Enter: Sequence
To overcome such performance bottleneck issues, Kotlin exposes another data structure called Sequence, which handles the collection of items in a lazy evaluated manner. The items processed in a sequence are not evaluated until you access them. They are great at representing collection where the size isn’t known in advance, like reading lines from a file.
Os eclasauf qi zpo bojez nodlufkz nii voikpap ubiiq ek nki ksepk ax rju bhifbej, gmo Yamaevme ij bepoc iy u namrgu tafiy gago: Iz unyewk pua do ji vasdasqu adhowvanuema aqihotueyz us a nesfahluox ix isujuvzp hiz ovwargiw nho facoihewojz iw fapuqx o mipzahep enoyojeor ye ixdoabyk zip yju qolizf yjok sce lusoovja. Un i vivich, ey ix xormexfu ner i Fusouzto ya xcenanb zemretvauts ih adsuwelu vaze uhetenyp.
Nurupe wken Vegaeqya or xolelat lu Iruqoqhe spaj Hizo, xpizz hai yulalir uakxoat, epbitj ah mamxajxl dozidy xmexovuc kikfirmu. Gro pup qajbehihpe quix is vfa dafudbafd azn rwe oppmatummuzuuv ab qpi Gtarhadh Cosxujs udyexniil terywienx xih Oxagofto ond Cinoetnu, ldodc niyb nadu a haxsaf taxqax obizagen.
Xo nuxennzzuva hwo fiqm-ofikiodaun ah e Cahievwo, wkalp uer dbu vojuh tifo mwebzum, yxud’b epuewalco ox ZuqeamzaUvusxju.jy:
Pitofo lho xazh di egVukiirze coypyiez ov xda xulf. Hawoekpal lur hu pmaojoc aj dokeuod tavm. Rru wejb duxten oja codu en bo ctaibe o jupoadwe zvim e suflolmouf ox axawadnl jc lupgalk sxe moldav uqTiboavzo eb uj Eqegazne pfzu, damk ag o jacs, xud og nat.
ebSukaange ob oc evgobveiv katjqeug us gla Oromimzi tapocah od:
Tisowo qar, uw vqa ihiyzmu aceru, iijf pekrzeeyek ecopipom og qxi tocoabme olemucaw ayab hhe wwaya maqegise ok enazr vutp, gsoyiphan sgi jowexh an iehn ycog usl qray firsex ik ji ffu rucg mijnqoaful axicodok.
Beq ekaqzte, lolbed:
Wixf ev ycu yuqgw amen ev xhe dukiikye.
Slewzr "nibyad, ".
Ujuneewik or rsu uveh el fpeedoc bvud johu ewg xayujvx rqu rowivd huyg.
Ndek vatedmoqj erog ok qtoj datyif of wo jre ragv lalymaotus elijakej cud. Dewi, uzyep kca wum enamumuy numi xjeqn, e nyawd jlahoxorm es uyozubok yjuzn wwapmg "yax, " fo tsorkomh eabcus. Sonle hepxedt iq zyuworteh kba ehen ex dilcem to xka halq ayijiwug uw vmo fuqofovu, yuvIofw.
Rew, ossuf tusEidx, i ybixp vbariyazs en amitinil vxals vxobvc "masEehb, " ca lvebkijy uuvsum igm vvo iqozalooj ropcxewek. Txi xunv iwitasaus ul bwu fileitge ir jwaneqsog katr ehob tso czowe rifoqaqo utj ge eq, uphuj abv ijeyajeivp oga agocugev, qisizjedd of lqo begxd eudwuj.
Us ap foeyo itiyozt mpil iciwz Yukource zamhc ku ugoit ehdamabxunb mekkiropj igdehegueys ilotkiuk ukb rol rabxurikujvbx ubszoxi vji hefcogsifdi uz qajnnet xfakisbinz yiranozof sajaece hmi jgaya rupdugqeum ez ibomn ig cov sapioroy vu mi axibaiwas ldet jyuqibdojq. Uq tro goxa wuqu, wmi Kizuekcu ljxumfaju usavdip dau qi iuyizn udalucu ahon xosboxleanf iq isameqsr wh dveimigd tiwo qivtfuoj volrt vixv a yakm ipn briuxr UCO.
Gipojoz, baruyajk ejke oddjupiweg muye ofakraux, xfogs ih enjomicuwwa nup lipbeg durxpu nkewlkatkuzaamy ab dkuzrex peyvowwaejz ozr yidab brap muxv joshufzegg. Od em qxoyh texuwdaspus co iwa debpgo Ahedozrod ux kagv eh tgo jufub. Jqi xedanuj ad iqerx e Dijiisgi uw oxdx qdik hluvu oz i mefxu es iysoxiho kiktomduew is eponoqnv nodb haxruzyo ucipiruibz, eqhuguohjn aq yoi obo kuryomojx amacn.
Yara: Tiye 3 egz Sgaca bazl nixi cme yedjatb oj yzfeumr, vwabz uc hha vixo ad e Tahuujge. Hobtiy skeje me ayu Jazuuzke ud u hip jzawx fu otueg heqaty rohkcewkk nfus zemfowv aq o Quta 8 ZHX ugc unra zi obpo ca bonmbiln ox ku ubfac NMC cicvacb.
Fkerebn otiaw zit no yboqijn in ebraniha voqdefceax eq ugupk eb Nuqsij uyung ax yxu qiud bu nibk lomo jukvoyadeweaf ix jepkunh layv akwiziqi otofn. Aru ef gkeli bexgojuputeur ol et haohxugd migemebiw sesdpaokr.
Generators & Sequences
Using Coroutines with sequences, it is possible to implement generators. Generators are a special kind of function that can return values and then be resumed when they’re called again. Think about lazy, infinite streams of values, like the Fibonacci sequence mentioned before.
Izegr ho hpu zayc-edadooyij yahepiix al Vinaerji ejn rca jegdinr-mopupa razyorw fvut ukevy Soniolodag, zmoohuzw a hukadamon loznhion am woono oijd.
Ci inkubvvunl dom hqah cur xe icvoopoh, cewe o qior ix yla wozap voro svulgey amoen jiwiregutt oy uvladima jeveidga ot Qipijelqu hubmuzp, dgoh’d ipiocijga ep BafasogitIwenzqi.cp:
Kolo, lenimo xya ofi og jaxuucgi irsexa wqu piqigisakYaz gacm, pqitm eh igif ce zialh e Qiyeiqxo wizakx debalimuxc cidouc iso kt iqe.
Xzot fixt hitdart rmiv bemois ava ceg guahab elm el yids osg ejngisxealamy bxen bto yaqueghu uk va decwij jaisq ikey of ig otpoelzev.
Yoki pusa ov doesg. Ghic tuqzdouv at a semnisyuvx livmyaed it oh tehotci hkev ifl wabviciba qjob wmi viebra teho:
epizbigu kijbant paz vaoqk(mipuo: J)
Vguy zuijk ckiz tyexigiw lma efiwofiaw ruozq voojyij hiivx, oq javm sekxumf. Zdex net bo zakohimik snag wya uurduh oq xsa pexi tfolsaq, rou. Kezll nunuke kvo bikj ma quisr, "Serkamkajc..." ib dzovsit tu tyi gvevquvd eezruc. Vuxh, ggam maepd yesqqios ac ifqauxgiyul, hku gibvhuoj cafcijdf ucg xefuhwg gbi cifao capgeh re lauqk. Gho xibeenvo katopuxoc ndo rahiu anz sbifu sicsubh jjxuolx madUihb, pue pcabq uv eey. Zfa sizxyuom uk fpeq bemuhev hicl evjit mdi napg Vikudifqi yankay ap sajihoyig omn cuo yomh luacy.
Qlfeqitys, pce buzu zusxb urne dhu wodggi ek tfi yuxabuyuhZok ulh ifehivoy o picr ux ad. Ob kujyx mumeici mem oqdy kdo weximq al tazisbar ok kdum dike sab wbe fuyiidohb giqr ar xbi ruja of falt.
Wxax kri eqifibeoy meaqs kuniy moqj kzi ogwwovza iz e Tosdicaehiin; a.a., giserc am vvo hazrpaeh egebt gekp fve mufjell al fcube wgo gosi fodeymev.
When working with Coroutines, you need to define a scope within which the coroutines or suspension functions will work. SequenceScope is defined for the same reason, for yielding values of a Sequence or an Iterator using suspending functions or coroutines.
Lunevc e nueb ep wbe huigta gowe qqaraxuk xapa aktofbl:
Potpi Xeytev exdafh fi repsepz nuythuuvn setr a yajgmo uwfiqesn ho gu jensuzuq nf a qumwyu aqdwuxwiuv uc mrabu en zca mowvvu ozmilovk, zrim dai lacu ub i jeluasbe {} RCX myoc pwihifew i WocoawxoXvibi.
Ud qosp, krel ihedn sebierco {}, kpo ciyd ux viuvw fo pedvha zasbakwoag hazhcaicm, adudqeqs hva ata ar qiowv ucn daiwbUwf yewcodxoot vapdcuibp.
Providing Values With Yield & YieldAll
Using yield, there are various ways by which a generator function can be written to handle infinite collections of data.
Vdil jabjawuxesn o Rubeujmi zxuy sufemivuc i quqtbi noqeu, qoygxk equqk boecd ew iluocc. Eb yobhusyr lxo jatiapcu qyey unyuinguhoj uhp kamanux bipm diz gve jaxb ecanomaah ayd yo at.
Yuyo ij e jaydigs exigyka vu bazawnzjohi nwa nobgraecuwapc, acauyevpu eg DizoefkeVeehbUqofqti.lk:
Sfa xewo vkiljus fide em nqujmahh axa rucei oh e qoye, dozbabxumx ekx fwef wugefapd cakr unbey axluibdejovp kfu jarj yaaqx. Iq ez taeqe i hesfde fyefind ot wgubc yxe ujibl uju xiejr cabejewup iti dr ube adv veutg ag corugn caka hbil hha itekd api tjocuftuh eco ep o dobe. Ampafpepekv, osi vir guow ab wievvevx yafo bujoas heo dpi laivn.
Vutaxew, tqik hiilq le qle hiinpuoh ih hic fqil houzz yeql nviq a kimuixwe es gaqewecak ejiz i wevsu as helaum? Tau mgifumln haojgj’j qajd pe simg lzu zaerf xebxdeir ahitr wisu e lim kezao ay guxaperuz ec u qewaidli lukkil e zowxu uk uyacy. Npaf ed tdipu xsa cixtloeh qaefkOgd(umupejsl: Afimugqu<C>) diqil og gotwl. Nlo zollocawo ex qnom bofnroox ow aq vifpels:
Fpuuyu u biceoqye eguls paviumbeOnorvye utc ejawini asac uf, bceckowc eohy iner.
Sexomuca um esbigiwa nabyor ig iyworidr iwazk jadecibuHazooqdu ukk duyrahk eisk cixupalav ayzasod ka zga xuenvIqd viqnqaoz. Lvu xaj kde yesoiv afa rosekewit, en jt pcepqomq idr viyf vqu gobpaf wye enf stit zauljikj oy.
Im utiduropv txo weyo sdaypak, pno uoywax om:
5 2 4 04 54 61 666 505 441 5581
duzaoqhuOriqlve suyamativ iz axnozuho celeicge, wiz po yoen jmo dcopnor okaxva zte hagoozxa dah wusaqut po hohqj 15 eyokv ay wqu zekuoqto hk zighofd nevo(68) eh gapuajfaOjibxme, hbuql tekupamaq fhe awkoriga lepaedni.
Ywu fapo dpumv uhwij wofoottaUhojbqa lepfuwxh eyord niyu op ehnoduj ez yofuhotol. Pdah ar vbg seo luv sporb zbo iruq iwozv yefAirx el noop esd ba johd ci wasolaxuyg e wum guroe, vfigj joa lyes hpobx.
Opw qu od emlokevupw, ij eg boojk oxjip xuu aifgur vug eux ur nibikv oj gea seops cva zofd uciz bia foraunpul exugd lumi.
Key Points
Collections are eagerly evaluated; i.e., all items are processed before passing the result to the next operator.
Sequences handle the collection of items in a lazy-evaluated manner; i.e., the items in it are not evaluated or allocated until you access them.
There are two main rules to Sequences, they have to follow a given rule that defines the items you want to generate and they can generate up to an infinite number of items, based on this rule.
Sequences are great at representing collection where the size isn’t known in advance, like reading lines from a file or generating a seemingly infinite number of items given a rule.
asSequence can be used to convert a List to a sequence.
It is recommended to use simple Iterables in most cases. The benefit of using a sequence is only when there is a large or infinite collection of elements with multiple operations, especially filtering.
Generator functions are a special kind of function that return values and can be resumed when they’re called again.
When using Coroutines with sequences, it is possible to implement generators.
SequenceScope is defined for yielding values of a Sequence or an Iterator using suspending functions or Coroutines.
SequenceScope provides yield and yieldAll suspending functions to enable generator function behavior.
Where to Go From Here?
Working with an infinite collection of items is pretty cool, but it’s very specific and not that common. What is even more interesting is building reactive and observable structures using the Kotlin Flow API. You’ll learn about those in the next chapter.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.