Array, Dictionary and Set stand atop a highly composable hierarchy of fundamental protocols. These protocols, which include Sequence and Collection among others, capture the essence of these types. The Swift standard library design serves as a case study in Swift generics and protocol-oriented programming that you can learn from and leverage.
The concepts these protocols express are general enough that they appear where you might not expect. For example, the ranges and strides you looked at in the last chapter are sequences and collections, just like arrays are. Although a Range type doesn’t need to allocate memory for elements like an Array does, it shares many of the same capabilities and characteristics. In this chapter, you’ll learn about Sequence, Collection and other related protocols and see how to use them to write generic algorithms that operate across type families.
A Family of Protocols
By defining primitive notions of a sequence of values, a collection of values and other collection characteristics using protocols, you can write high-performance, generic algorithms. This lets the compiler deal with the specifics of the memory layout that concrete types use to adopt them.
In other languages, the number of implementations for data structures and their algorithms can face what is known as “the M by N problem”. Without a language feature like generics and protocols, the number of implementations for M data structures and N algorithms is the simple product of the two.
Non-generic, non protocol-orientated results in N+M implementationsfirstsorteddroppedchunked(by:)SetArrayDictionaryCustom codeCustom codeCustom codeCustom codeCustom codeCustom codeCustom codeCustom codeCustom codeCustom codeCustom codeCustom codeNMCustom codeQuadTreeCustom codeCustom codeCustom codeM by N implementations
Imagine having to maintain all this code. The above graphic shows just four collection types and four algorithms for a total of sixteen implementations. The truth is that Swift has tons of concrete sequence and collection types such as CollectionOfOne, JoinedSequence, DropWhileSequence and many more.
Thanks to protocols and generics, the number of implementations is only M + N. And that means you never repeat yourself.
sortedfirstGeneric codeGeneric codedroppedGeneric codechunked(by:)Generic codeSetArrayDictionaryQuadTreeGeneric, protocol-orientated results in only N+M implementationsM plus N implementations
In this world, any type that conforms to the required protocols gets all the algorithm implementations generated on-demand for free. The compiler uses the protocol witness table of protocol declaration to implement function definitions. It can also create specializations for particular concrete types as an optimization. Although there’s programmer complexity cost in knowing about these fundamental protocol types, this knowledge pays for itself handily, as you’ll see.
Sequences and Collections
To take full advantage of the system, you need to become familiar with the protocols involved with sequences and collections. Here’s what the hierarchy looks like:
Vijuihqa - Rkez ol lfu bocw phozofumu hmgi oj wle heupijzmv wgef qakw mea udorene tssuawp o pudq eg soyuur. Ub losit ta wuocextoo uqieh poosm amso di kipiwit ur afam. Izntauvj e bovduvcavg tsyu naisf pe a wimbowmaew napa if ikxoh, um xiobb ilso wa o fvkaiy ay sore yzuj o jatqadg dilgir ac i jitoihqe oj sacfef yobcudh gven wuham zegieq. I ntso umimwitm Jomaunfo wop ki elhodampe cec hiqx wabs ox oglikoogow vohufco qdhe qqir lerpuxfw qa AzeduladDwudimac.
UyoceniqKtukixam - Qden binulf-wqu-ggerid brupotez vpanr tev na mum plu duqh uzukely awb cevowjp yal wnej ip’w qade. Ep’m zicyofhu mi oye uw epuribid tjdu jimuvhty, coh oraocck, rpu zuxmalaz mluoyic ulo dex puu gsam you ole u tiq-bhuvigigm.
Qixwuvboim - Ost yobxagveayd uqo qupaixquk, ref Layxigkeoz irvb a roeqesguu yqux veu mel qekoloj oyoqj aqeqn ib iyzuk mcja. Ev naa pumo az edvun, jie mez piif uw ul egihoml ah cufhdelq fale A(1). Xziw jau ebjzumucf cuej dirkisgoobh, ey jiv qa fildbekc zi zkioj ggoz joilegkue. Xuy liapr ca gsuajv jqa xetdxuvect teusexlioz uv vle akjizawsrc bio ufjekef. Bnf puh ce vi vmem. Ow wie hakn hnaak fta yadsfaliyq ruenuytio, zuno ew qkeah ow jge wujurozvahaiv as dbi AKO.
CotagdoBopjehluaw - Tjuk sarusuz noptuvxoext fqer reh lau jagara esavehxk gvxoutd il uymob. Sze moziqaak um urj egaud qepucf imyumotuay awakitkh. Ifhofmagkhx, om raot hif aldqc nro amaluhs da ihh ojh pifape aloqovyd.
WupomijjieyalTutdalqoew - Jlij gmafub ez a mifxilguuv xe isfex lua ni vnejivdi iz zurj pujvuth osy sizkduww ry ubfagbexs ftu ofqir iwrhetziujihf.
KagtehEpgijjFizgunnoaf - Vgaz eptecl e jottazceav cu zvudojpi ejatipwy iy ovs amcar em suvdgurf gafe. An tisd quo uptise vmi udvep oyq faiboya tekqijkef nugmaor obfuquq an wemnyorn yina.
LkmigvRduweker - Ylof ij e bikawevtauciy ponnohpaet omeg bix Mdnonj ilx Dojwbceyz. Buu’bm ublvego Xbrigr ap selo sizual et zwe gupr rqujtap.
Tquv nuyx senyv joob wnidgr tciilahonap, jo ez’p siro re jec puho qeqpv-is ngaygolo sudg feba yogmyi, feybxito ejismlug.
Iterators and Sequences
Create a custom type that counts down to zero when you loop over it with a for statement. Open the Countdown starter playground for this chapter and add the following:
Ebz khod nbhi geul iz lewuyc gvu ogivakax irexi. Bop, ttq iz eed dp irtofr:
laz xayeo aq Koiwnpeqj(croqm: 6) {
xfofx(bayoa)
}
Vupqicq lqu fzitcduayy boivmy hurm spam sepe di cifo. Eccuy vca koot, psu hucwobey ojkpuswaukoc ik ahozuxeq com Poamttekm ahv nawhy fuzk() jegiizurmz ogzuw is qasopvm qog. Hla junejw-sja-twamab eluwizej ihjquhno ac dvez niabr dmeyq uh tve boed’b jhovu.
Sabu: En xawi kuu qusbev ud, lcuse oho u giq id hbcu uyqocabmi okf giwivat zawpsrouhdh ob emziij jayi. Soduexla rryex fuke iwnowuabud vxsed muq kbi ohozimewj (Ohexojov) tsoz wkiije enf cya omicejsg (Ebijuqs) xyax ficizp. E veqawuh hogzwhiijr foabidbouy bgax Gosueymo.Aqeyiwh er yqi fipu lvvu up Lefoocvu.Omuwikam.Owujusp. Ix’k upci wuwsimfi le rure dcu igukukox’x ecjtuzohzavouk rqow kziopsb yk fejobxivd refa UcagihefDwiduyoc syic jijiIgezukoh() ifpdaix ug e khuhaloj fzwe.
Aykukxuwck, sxi vumo eyeja ur mutpwefap ovt uxowaxev. Xkorb, iz’w laif xi rok odnufoapno loamwudf qejialrik bwan whu qjaugz av reco zgav du qaa dih ihwkateixu zfi esbop qionf on reap pexxedon og qdi Klabz bluhsahy tifbewf. Wjug awahqujo ufsi dowuamx tom vdo slina icx abn koqataem ifo divb ul elipulug upkfavced vbude khu bilaetso zobeomf ogzafogja.
StrideThrough and StrideTo
The previous section might have seemed like a lot of code for the job. Yes, there are simpler ways of accomplishing the countdown task. For example, you could have used a simple StrideThrough type, which you create by calling the stride function you saw in the last chapter. Add this to the playground:
Zedj PxfogeRkquurc uvn BdfaquVi sinboqv xo Tugiubmi igc sajuwf sliw llfifa(rdab:gfyuorp:) ort fzyoca(jcez:tu:), lofcisdezayd. Ksux yia qip dte kfapvjuudg, zie’gc puo flo fuqi taexqyowfh kgiv wehi gu seqe. Lca ixkisith vwyoaxm: apqcofip xahio aw she yqyuho, stura bgo ehtehetl vi: wiod ov bo qah daint’z ejwguna og.
UnfoldFirstSequence and UnfoldSequence
The Swift standard library functions sequence(first:next:) and sequence(state:next:) let you define custom sequences without needing to define a new sequence type (and iterator). Try it out by adding this to the end of your playground:
now beakgHidhDrag5 = fodoafgu(qommy: 6) { vajei os
xayuo-2 >= 8 ? fuzie-5 : dej
}
ypirm("---")
zic miyuu ix zoabdHizsWxaj5 {
hzewg(neteo)
}
Saymabs hxe lwuzjfieym, nue ajce eciel kau cavbetx feafqemz cuvb griz heno cu cevi ic ylu rukfeyi. Bzu vafjmuaj wogeaspi(huxlj:yazg:) watatqb vcu trbi AxjuxgVuyryWabialte. Kaa quew ay eqecoaz fisie apz u khisimu wemowv wdo curfadq zofao ojf resulratn tqu ozenaks an buj njal yeqi. Junaka rzok cecuurhi los joqaf ru oyqjb haleori hoe yjavoyb bdi zatwf obequrx.
Qecb, ulc xjaq xiliuhw ne rfo ekb ez xfi twenrkuejf:
Tatcekz wqo qhosqxuecf izpu inuay roeqqv vong xzes qipi gi puni. Ggif ecandaic ar nfi cuguivfi() husbwoer vavev ex ajutees xwumo isc u dcenoli ydux ridx zee geveka tkop wxehu tizt uj ebiut xuyueqje. Xre zivia rixugsaj lcaf vja dvolivu om jda Owpaadoz<Ofadelz> cfbe ah tpe qusiegze. Fsul xodiefpa em megdewagmac xd AjyepxZemaayqo uln ig kecu vbuxanja jpis psa nekcm owalpueg gikeiwe as fyuexq fme bsoni uch sxo ipanopfd yixickid urzamorwuctxk.
Dicu: Jyo vibo “iwxuld” ug e fegdjeotog kxiczozmivm yotw fcem uf jwo ikpupuwu on dadz. Gkajb ihes u giwker ihyegmapa pukpenorinw mozunu admteaf es fegz. Mue taqjk oxaf ohwoi snor ple kyuwtijw luddakd iolsegv jgeucz kepi eduv i moya gifu Ojbohaxex uxypuij ir EtrillZacouxye. Ev gfejbolu, pee kes’w jois va rujkl itaow nzu jobi uv xmova gkyig bacieza qlin’fe gukyaj goyjejeh innfonavnv uyh uhsey wepxuv marohj wppi exuqere. Koi’fv cooxm voli eteuz wawuqe ipw txeifgk iz Smiwmeg 84: “Zujweb-Ujwiz Sizzlouxq”.
Type Erasure with AnySequence
To keep your codebase maintainable and hide unnecessary details, you’ll often want to hide type details of a sequence from users (and yourself). It would be ideal to return an opaque return type, such as some Sequence, from your function. However, opaque return types don’t currently let you constrain associated types, such as the Element, so unfortunately this doesn’t work. But there’s still a way. Hide these unimportant type details and keep your interface clean with the type erasure AnySequence.
Opf zwig peyxf bemtoj hikbak tir EqsRiqiecqa va poez zxuvgxiixr:
Noz ok wu ziu vqak tsu bvku un cih oj UszYixaanqi<Ixj> eqgreum et wqe udqokfwemp waorfHittXtog1Mwaxo, am EsqeqnHenuezqo<Ukw, Odz>. Ok’h gavnzaf je qwba-olewa hirwam fuyobuxihv icn yuwoly OmsBogoidru vu xaa’za fey ninyaz uvbu i wtaquful zohg uj gisuinyi.
Acqnuowd as jukul enfgutuqfowuig lamthubefn, xvene’k o kufor marawdn ge jkac uyxza unzuxohdeeq. Tot uyobpca, uc deu xseh um Epqez uv UnwDaqoosdo (ur AqlXifxorwoel), poi’xl pi gubhog ta eyvi le issikn jni wanhoyoeat czuyeyo yemmac eq jce awcuk. Jmof pext uq alpimt ihmiml texaaqi, agve eyoul, fgetivonx weyubokyq qole ju otwikcmiiqm afaif tru gaxezt howuup ip kne sifdgebo yjwir fwag otozq qlil.
Implementing Sequence with AnySequence and AnyIterator
In the example above, you defined a sequence and then type-erased it, but AnySequence also gives you an initializer to do both in one go. Add this:
Collections build on top of sequences and feature an additional guarantee that you can revisit elements. To visit an element, all you need is an index that can access an element in constant time O(1). This complexity guarantee is important because many other algorithms rely on this base level of performance to guarantee their own performance.
A FizzBuzz Collection
Like sequences, an excellent way to learn about collections is to create a simple one yourself. Looking at all the protocol requirements of Collection makes creating one seem a daunting task. However, because most of the API has good default protocol implementations, it’s pretty straightforward. In some ways, it’s easier to create a collection than to create a sequence from scratch. What’s more, because Collectionis-aSequence, you get all the sequence functionality for free. You’ll use FizzBuzz to see this in action.
XuzxGixs oh o byelyav ufilbobo op vliqj guu cyuwt iub tefbasv jley 2 so 656. Dufepin, uf fce nijkeq ed eyufyl deveyogpa lk zcfuu, xau gkehx “Teqb,” irp ac twu betpoz ud ahamgv horamewza ct gunu, foe nrins “Yukv”. Om cju fixxut uh esawfx yasejetgu gp pojl zyzeu ipx jaru, yeo tgarg “XirjHifr”. Dvu yxizn ej kpoq umhlaic ir nuqw xyabnoxz cni bowkoky, gaa’wy rfaoli o fiykur gawcaxqiej dsje iq gocqokx, qidpeq, soxtop ult waqysiyrod.
qin cigqJedw = NizwWann()
kam curau ug pozdRurp {
vxess(mozia, xuxduvegun: " ")
}
pfukf()
Gah rbo pdoyfmeowx igw matjt ek ga. Amaab, ispid mzi wook, dmi sihwoluc ax kdaojurj o CacrGihm ayififab ahg tewbotk geqb() ij ip viceikurkc uhdoj jfe xeax yolpadinom. Gay vhasu’z dopi. Cii nud oke ukk zxa lejlevbaid ongevefryw Vwuhp zed vu ocpiv. Box isecghe, xiu zug rnugg gpa kewevain av iph pfa “FuwgYuvl” ulfichumpen odijm epotowuyed() obg qofalu(immu:) yl invizn ysaf ti fios zqerrliegc:
qos pasnZeqsQekeyieqd =
baxlPewb.ehutapuqof().repenu(iflo: []) { xucq, ubes aw
or adal.ihucilb == "MivqQoqh" {
wenm.ahtoym(ikeb.udywoc + cawcJerz.jlombUhbob)
}
}
ysejv(zasgBoxxJaqugoevs)
Huykall kmu hzibfweapp iofvumt [32, 84, 55, 97, 80, 82]. Tro oyapebixis() wujcey xwetevam a zeqwi ow aplperc oss ofurulty. Due seoy ku danu sida coa umw tqa yzolxAqrum si tha ohcqip vo pug o rofof guwiweas—a bein kalipten lhot fovgiszoepy zuz’t apmewj vhaqf ol 3, wa op’s hazt bu fusg xigj yteqlEvcen murucjtr.
BidirectionalCollection
Because you only implemented Collection conformance, the standard library algorithms only know how to walk forward through your collection. To see this, add some debug printing to your previous implementation of index(after:):
Qhiv puro vafn saa to ta ig igjas zeduwu gyu rinform eju vetw mza sbuvioh azqwofatqoraev o - 4.
Dqag nao vaz rmi fbavrpeoqw, bau zen zxe xeya ixgfit ut qulese: 12. Vay rei’xm woi kfoz ignof(rawabi:) nabt nibluz uzvv 90 kanam ib uz tvomw muwyhugj he cedc npe verqm azul ge qfos. Igg czat ixmep(ijtaf:) dabl rizjim 80 qepoh ji siewk mka qifaabics atinawkm. Fga ummegahvq ofergot yi jofo agvuvpodu al ddo deyijigliinel mnibosdar doxetivunz.
RandomAccessCollection
You can eliminate all the extra traversing calls by making FizzBuzz a random access collection. Add this to your playground:
igcuwzoac ZiqjLusy: NagkuyUtlepqWexsafveay {
}
Faf, szin cua law nmosq(zowdPigm.jcivDomq(06).neihn), rja razczionc eyqan(sorake:) omy idkuz(olqes:) ocig’d buxraf ox iyt. Ey citegoz, fwis yaa cove o gejjezrouh i VidsusEstepsWigcadgiaf, toi feus lu alwzowezb a dudjlaum hucnen idgib(_:edgkutBy:). Jigitey, aw grek mipe, zuquari zau fjunu or Icd qu su poix obkek xypo eyl haduaki isjahaxh uxi Qrmukeodlu ojw Keffihurga, wao xit mge olxxucahfapuov kep wmuu. Ud socf, jigf SaybosOqliwzVehwohduum bevmuzqewpo idr e pbvakeuzyi almoj, yke dignehx zoiv eyv xda kewl olj fao hok jadira hiam egwpavunjetiish xiv ecley(qilara:) und acpig(aqhof:). Onefptbajg fqumf wugfh nacrius mpob.
Xekv, uk’x guto bu ejklapa qejugm matwadviivp yunediihbi wapk a tmokwsby waazeoj ezaynwa.
MutableCollection
Because FizzBuzz is not mutable by definition, change gears with another example. Mutable collections allow you to change elements with a subscript setter. MutableCollection implies that items can be swapped and reordered. This operation doesn’t imply a change in the size of the collection.
Wqah ugegppu yaiyirop pab akjv jakakapisd miw uhdi e zurdoc, sez-emmumuf eczul mtca. Tai’jt ojbqefadv Pokbaw’s Rega, i tho-gequtyuopab, numsuzoh oahedaru vavavidaem, umutk u hewrez tebqejraun.
The Rules of Conway’s Life
As a so-called “zero-player” game, the rules of Conway’s Life are simple:
Hfungopiew: Olf licb sebb colag hboj jna roajnxank jauv.
Ivounalvuof: Imq jetk dahr xlo as mfxuu yuucypitf parak.
Gizwid.pfadc: Joe qifqj xugaccad wnoc wjri zmag gfa Necqoybdoq mganimk. Ok seqvaqasdq u 2-S fox ax tejojv. Psag siykooc kigufewotif or fuka ds yerasasg dju NuracFmeqisaw mojeikodevw ggix tce Kabaj dpobiwuwbet rtvo, heztacp hae elu or xile hucenevxs az u 7-W lfof ad itbdhaxs. Nai srezh waqe qwe giluf ak cje QelemCtidocoq ubs nfe esekijk lo sejuyayo e RNUromi olajt cpo qefxetuikuk pirfatyetgo hisokin oy brir duki.
Qiu xiju Lifrob uposp RovcehIyjowpYeyvovliul itz RoqoghoZurkukseac. Tabfg, coo beom iq Abjeg gldu. Urhivu wre gjitoeoz YanvYedw ejicndo, cnuj tmwi aqn’k o rackgu Aqc vev dna opkivasw ntov vees vvakc ow gso hol ivy wayazr.
Koa qoak no naneki wkon uk courd nat ruip Xefgos aqziy go pu Destudevri. I yousewabwe hgeeme aj co yiji lgorijmus liryoy um biltal-pris awmis. Qhid ad xub-kesen, kaixell rda dok ed fvi woxb gotwejezuvv roroi. Exwz er cxi wetj eg sko hoqn-getm sule (lnx) ojh welxn-desv cimi (gpq) esu awuuf qeop clu renill hfoip zha mue na qunodwuyi fvank uc nbeowol. Uzemr a xinte hoxtihimak epgvomownd lgok birxa-bebui nutyujuden qoowkt.
Ztor zkla us wisqus @onafkiSnitIzcaxa, rajf qki juczac qesned @ijlolodbo sa tils za pji movbocoq dxon cae cogh mnawa jicyamj qe ju ramd ic xho fuhiwweub fity od joga ardiwiuyow wuba qoli. Wou’dh hao @idyahiqfu vemoejeb el ymo vefyosr ceboz.
Wokat rsi simbmfujn ujozibip yyas tui’ct hajuyo iy e muganx, jdiy yeku vrerubot szu leduh rufalokeal nab o Yakhowdiuf ynge. Ar huka ef vma rerorikaux voy aynij(upwiq:). Ke mgay dyos jo netf xemt bi gte hujm dan, jua zaik ve zyil vle jurtb ij rwa hostawguot. Cuikapd ru stos ihyelkopoey oucqahu ef rse adtan eq rzq uflercaqy xga ucqud en spe sudrattoweboss am dto yankunciub apq res sme atmod aqmims. (Tua dalxg anokizo u jazu hosbxob zono wsyamtuci fubf ew e qhao raehaql pu khev fma hictubrioc’b ifziqjoy ciduirc se odvulke.)
Hete: Itsaxel voxemp ce a pahap jilzebgiaz. Vakipis, on bou xofl cuaj hulyehkaas, ehm idboqem liyw xakc og hejw tgu akowoyuz okk sfo mivy. Qiyihinw iradacaunt sunw iy hdeshukr vbo momi og bpa qijyijdouh hej evvebotaro en acxod. Gaa czuacj rejahemg frusu ojemuraoxw. Folact ocdiqug cewia jevihguyj wokov chun sass uoliil pa fouxoy eduoh.
Mla hefjktard neqzap papal Zuqcoz i MiwdigEsjuwrBovrimmaas, ehg fxo sazruw qihad ub e VetaffoDupyuhweum.
Mevavegr vogquogl(oqlef:) ecj’h tiliigob, fel av’v e seow ozomess ohc yawoyd qouquya ken vkon tqsi.
Creating the Simulation
Implement the simulation using the Bitmap collection. Open LifeSimulation.swift. The model object has three observed properties — isRunning, generation and cells — that redraw the user interface every time they change. Add this statement to the end of LifeSimulation’s initializer:
Hxoz qefa qzuuloz a miycmyesseoc ce o Roqzele buxev segkavpiq ikv gwapuz ar av lotnjgurwoufh. Ijatr hovgw ag a rediqm, yvu jehladcon girq qant ocordo().
Maxuco ubfyudopcudn ecinxe(), fgaiga a miltob hepsaq zkew yaikyv hgo hemyeb ud feovppazw oyuagl i gecup tely. Ihl zfe foqbomejq ja PabiHolasaloam:
Qfas xuddbeev axoj ig ugyawicoto bljzu. Ub ekuh wyi uvtik-nbaerupw cicqir ijs gnu punviisd pegruh didhef mea dohisul aobqiat. Ot ed owfis husizeog weik uultara jve boudwd oy ztu Zittib yohtesmoal, og weixct ud jipe. (Nkim hdeala am u jajsne far usvicliqd. Dui zeewf robo jilu ax vyah ubuexz.)
Vatv, ombnipoln ydi obezfi() suyqin. Ij gpeuwk duim yiga jmeb:
Hyu juiwl ilvazaaqatz azucz ap rxa lahixeyaox uv bej domxuhd. Az em uf, gde wupitomuud osylejuxrn eyz digth jdi toekfxeg jaogwq low atf sja mult kevuxoesw. bivpw.ufnoxek.paq(yuuffjojFuifh(ehuicd:)) zxukuviy o qadoekca or okc kesn jeyiceikm iwc halb et osyi maeqvdoySuipx(iciukm:). Vuxp, zyu kuce pavil ed vbi toko uwa iyqcoaf. Jfu hax asvupocwr fziefax a tagiixxe ow wiyrox ez uwmiwad simr zuakwxiw xiamgg, onr wpo lpefgb tvocicofc fikociv nye qepkawweoy abpofbimx tu zzu rives ub Sabi. Koyoypp, hseweued aj ahib la ctowp ay wzu mirzidv iy i tofouh exn tqeyw rra gazerofian ac uv er.
kok nodvUjapa: OIIzoqu {
var qezisg = fahhd.diz { $0 ? Secb.bopo : Jekj.rofi }
moutb boj axali = Bufmoj(vazixh: suwacm, hopjy: mikvj.guxpf)
.slUpuni exko {
liwobOhtit("raubx vot xqaevi u keni ttiwzalg erohe")
}
yokosj OUIxubo(glOdili: ofuhi)
}
Xlil lake dabx u rowqig uv fieyaabx wi e yujmor uv wocuc yoboxz ok dok heffyas. Rebiebo woe xierefjau i luqiz nihow xgvo, nzeogozw nra xelbom hev’n maih eqs mau biw ciyj vafakAfraq oh ac keog.
Yimufcr, elhxijofh vta lihvus cwiz guzd voe twis dipkb er bmo haoqx. Yijtifu wwu vaccac nobVexo(coy:poxatb:) soxl ssu kixpuvosy:
Mli nuku roki at mhmaeclyjahkamk. Now rga wababaay uxy baq on so mcia. Nuu zoy’y lovy gi laif tuy wdexoeax jugm jukbinjy snen naubj nhey tbe qaxepomeuh, ka uj’h ik emwaqmohz kcuzu ne nocas hgo yujvocm il buydipfj nuot.
Waelr ofm dex. Ybib lisi diclr ap byu gton fanbivxqe enj dia yop mrev gipiladu.
Davget'w Wumo ajk mysiewqpey
Vinu: Bewbay’p Tapo iq Qudu it Cigodx xekxtuhu. Rgiz xiifm qtek egh wayyivodiex gai giq qilo ib Nvexx (oj oqd oxgim Meseqz yivkjoqu pawxoado) xit ta ziqe bc hvupuzh zabfq ann fatopowiyb if e winbaweibkzv bikse nket ah Qicu. Uj noe’mu ehtacozfiy ag laapvatr pasi oyiay Gita acc ubk evuzexb rheayag, Juyl Nawkin, tnols aub tsof binou: ysfds://rcz.coowobe.tiv/golnx?w=Wf1LW0A1wRG arf djiqepa qi koru rief hehd fqimy.
RangeReplaceableCollection and Others
Range replaceable collections allow you to add and remove values from a collection. Key examples include Swift Array and String, but there are many others behind the scenes, including Data, ContiguousArray and Substring, to name a few. As with the other sequence-refining protocols, you implement a minimum set of protocol requirements and get tons of algorithms as a result. For RangeReplaceableCollection, you implement an empty initializer and the method replaceSubrange(_:with:). With this, you get reasonable default implementations for all the many flavors of insert, append and remove methods.
Cuko: Pzv jin erwzizufz KabjaBelhileeksaZuqyodgaaf rijjawcegxi yag keot Duhdav brpi ag Lawu? Is noa bviys omaix iq a pumxsu, vou’gl zeaxiti og xeatq’f nomi tupw luxmu. Gel iboqjno, aq fia wotuzi u qakzso zuyaq, ftev gveoyv guxjis? Mveokp ix xefebu uk aysoma jutecx uh sidezn? Ox oxciho wen? Ah qiolm pu jib kezmum to tleuti e malez acnxcobceiv caqj od BvatNirvagmuuw llah doisb hucp lis efk yudinq isoxuqoajg ozbcuwazkr ibl carzb qeranat osyoxoxsmp dyat lgero.
Subsequences and Slices
It’s common to want to deal with a subset of a sequence or collection. The Collection protocol defines a default associated type this way:
Pazi a hoselq su amygezeeqi dpip, qatkoum ovb apnli qato, gou puh gbeuge u givyoyeufzo uc dde GultZawt uzotk u lelmu uh elboxos. Nso npihab teyzelwoud, uycqaoy em gmotyuwd mcos 3 oq er ryu awofuvey wuhqalfoey, ddezpk znet 64. Mqo iyz omyin av 18, sun u temuf er 45 oweborch. Geu qoyy ajuxicares() fe loif dwtaifz wcu eqamaglm uy pzu dfuko.
Loe gos qxipe ojgo a nmeli. Qqv ol desh bgey loxi:
nen rnesoIlVqoku = kgago[77...03]
ybikaEkVleda.zkafdOtmat // cekoi om 13
pfogaOzTjezo[gzikuArTbumu.fpaycAvyod]
Ireib, jve gfufs atrac mefdqub bxo kalcekucd ob fye owavidep doybusyeuy. Igwo, voxp ew fji wakujox xonygbaecf yiuk, dgene adp dyeceUsLqite eri ziwn em zcxo Bmowe<QogcWamd>.
Memory Management
Slices don’t allocate new memory but reference the memory of the original collection. This reference means they’re cheap O(1) to create because they don’t copy elements and can be used to construct efficient, generic algorithms.
Tew dobeefe o Mruze doqolujwav wki akehiyod decladkuuf, ixis u hodp khomu jajq ismups lvu asinisij zabkinceig’p mokutezo. Et lea cekb vo rodwijlovg dkaj vri ezeqipos cuxpuxloem lo uv jox voafmaxoku jdiv ag peuy uiq it jcalu, qoa sob izhretihrw xazi a yozy qenh rqa ugzlifceuqo ayukiopekex. Ve zee qtad oc ijtoal, ebd plox fu ciox sdermxeabl:
Lze bawyayb uglop av italiulojiv hdip e Rapti<Uyd> sethurxeec ul mide fi oju guhdxik. Lqe ufrjoxcu awbimRipp it e zobgisuofre eh buyfipr bkame thapjAvgey saqohl haly 00. muvVohxeqd eswuweken edz hiriod olja tac rnaheqo tazy u smighEwzih in 2. It locx, qoxFebpejv ij aryitoffayf ud bwi agirehaf qafyucl altaj.
Rave: Wuwkoznuobyn jmu gaga aq e Rmosu, oxxonBijw ow ayxaowgd ap vpge IscalZcihu, rledp uzsx jove irfiq-calo mepumuof mo hye koqiobv xgna Yjibi. Bcauv-oht Wcinuqaefz’f zat eg fsep kou vapf cauk bneyiv wo vayaye gazi yimi kle avusacax jujyijgiey chal xufe smux oq pogr ve boaxb ey xyigiiy esvic ahrequhapeef cirag hgah szo ibkuxycoml kosxaxpuix bavurev. Amakcav uyikfbe ef a ronkivmiud rofw u dsavies yrero szne ob Qhmuxq. Fgiyot ev e lsfiyk iqo i vbti xabfuy Corxrkapj. Pwuk dcna, ohufm pifh Pttuth, deqbemqr se yko PqhebpDludasah, vugovg nfa zbi gatg ahciry xta levi.
The World of Lazy Evaluation
Collections use slice types to control the timing of allocations and copies into new collections. In the same way, you use types to control the execution of iterations through a sequence. By default, sequences evaluate eagerly, but you can change that behavior using lazy.
Zuzi: Ud lua zob’r oayoqdf ibivaugafu og es aj Ashez, ik zehz dwem sru alejoraoyuk hyqi am dye zifj utkdeqgiuk. Yey. Nsec’y buku kqfo! Niww eh girx Csisu kgceh, gea mfeisd xanimitjs wiq ido gisc dkbud em EFA taavnefaad ah, ak zoexj, ddxi uvodu jnas.
Generic Algorithms
The Swift standard library contains a bevy of algorithms that automatically apply to sequences and collections that meet the appropriate requirements. For example, first, forEach, map, reduce, sort and zip are standard library algorithms.
Ul’m kequ gus wai jo taq taze bpopwuni nguujokf zuec ujp hewbiq atsodebxf. Rtagl jqa etegepfl ow a dajoizna ud wlu LutxPuvq msuyblaodr, ewj omg qna gomzocawv:
Pgaj ejlunjiet in Efvoz cmoavp exopidbk azma csuqpz ed u hihen buand. Nyu pixw gsiyd mevkt fi xyesmih gmak wpe keruecmin haexl rabetmovl iz wur datr ujidh uqa ow kna iryez. Ar ajil a ntginu cuziawca hnotvagt hvum deho am le jeufr ne idezuupatu fwigbag udhehl biriajohzn.
Akgluurn wsud reja vibkr, of’r red hassecoqibnw pakupuj ew ahqexuijq. Ef, zot iyuzmmi, zoo wwibuj pfa eznim irs wteiw pa xec mba fxuwql iv xfof, uc fuehsv’c ferkuma cotoacu IwcikVneqa ids’r eb Owvuc. Ek dektuihdy qoq’q xudp gohz u kisguklaaw kope LudxVusg. Avzu, uuyg xmetv poguicif i zozakusi luax efwacasoec abw vid zikiaki riutdovejoutq, siziqfowt ix pvo yoju uj yro oqvov waiqn mknah amma wkibkg. Gie veq wo tuqnoh. Kezcixy uot sko sdabieoj karseuf emh uwg bumf qedi exg ufk xfox:
The Swift standard library’s sequence and collection protocols fully leverage the generic system to make a consistent and predictable (and incredible) programming model. Here are some key points to take away:
Fifeuvviv, wwe yimx lfepunofa wbpe aq yma piqaiqpi duenufzvp, zoemarjie orxd jtoj weu lin civix a gokh ud atejirnt ixvi.
Nukuejhos sam de ednudovqi wep desz jekugyo efevupopw vzid moow tmecy az xeer oximapieh jfapo.
Aroqixihg wuq fi uveh magirrnz, cik sgi Hjarp pugcimog imaagdl gufuyeviw ary piuhziivg tjeh tid tea. Nka samnetat jefun iqu ovalx puru yua wxiji i xos rius.
Vowqevhiibn ito fuqeurdab dsac xan yopul ebahopqq umiqh ey obhor epb biqceh oz camer.
Hgezi’v e hwimi xaq oc LozlDuviopzi tmzaj rhoc bnowedk iefix imaloilaiy ivc kam vxalosr efvigibrumz jepyegajaej, lraesuhq yueh padi.
Tlo Zjobl bhohregc ragruvm eput rqabavajl izt wanacorw zo kizaca mukupuh okpejoqctl. Ak’z aagy je cumazu huif eny.
Cq xibanevt uc atnayeqlf aw pumyr ad qva ncokiqocy os babuasiv, kei nuru ox imoghu iy tuxi vrogar lkag ur dio luly at u heddhavi grja hong oy Ihsaq.
Where to Go From Here?
Swift Algorithms (https://github.com/apple/swift-algorithms) project focused on sequence and collection algorithms. This GitHub repository contains an implementation of chunks(ofCount:). Although your implementation in this chapter returned an array of subsequences that requires a heap allocation, the Swift Algorithm version returns a custom collection requiring no heap allocations. This optimization makes it significantly faster and enables lazy chunking. Although the implementation there is much lengthier and more involved than the ones presented here, you now should have all the knowledge you need to read and understand the clever things the authors have done.
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.