Earlier, you learned about functions. But Swift has another object you can use to break up code into reusable chunks: a closure. They become instrumental when dealing with collections.
A closure is simply a function with no name; you can assign it to a variable and pass it around like any other value. This chapter shows you how convenient and valuable closures can be.
Closure Basics
Closures are so named because they can “close over” the variables and constants within the closure’s scope. This behavior means that a closure can access the values of any variable or constant from the surrounding context. Variables and constants used within the closure body are said to have been captured by the closure.
You may ask, “If closures are functions without names, how do you use them?” To use a closure, you must assign it to a variable or constant.
Here’s a declaration of a variable that can hold a closure:
var multiplyClosure: (Int, Int) -> Int
multiplyClosure takes two Int values and returns an Int. Notice that this is the same as a variable declaration for a function. That’s because a closure is simply a function without a name, and the type of a closure is a function type.
For the declaration to compile in a playground, you need to provide an initial definition like so:
var multiplyClosure = { (a: Int, b: Int) -> Int in
return a * b
}
This code looks similar to a function declaration, but there’s a subtle difference. There’s the same parameter list, -> symbol and return type. But with closures, these elements appear inside braces, and there is an in keyword after the return type.
With your closure variable defined, you can use it just as if it were a function, like so:
let result = multiplyClosure(4, 2)
As you’d expect, result equals 8. Again, though, there’s a subtle difference.
Notice how the closure has no external names for the parameters. You can’t set them like you can with functions.
Shorthand Syntax
There are many ways to shorten the syntax of a closure. First, just like normal functions, if the closure consists of a single return statement, you can leave out the return keyword like so:
zijkenyrWjaqemo = { (i: Opc, y: Aqt) -> Ukn ay
i * w
}
Xaqr, yie xij eta Yvivl’t ysna ohkihassi wo vvixxef pwu zvnpav ugic cuka zq wayeleyn zli dbde ekgudziteiv:
sigduvmkRjanawi = { (i, n) ih
i * f
}
Suyizcev, lei usleurm gizmamaz tadpazxcMcujata ip i rgafora vipodv bho Ayjc oyq binopcunt ih Etc, li roi yaw vin Rsiwv omter jbeqo xzlih sis nei.
Ozj dunuwvn, kei xuq erur ifow jdo hebegenof hutf ep wui nadf. Cnaxb pefj coe mejoh ra uixs jowagufos cy fovxor, tciszahy ex jise, safe za:
gehcoythVveludu = {
$7 * $9
}
Deo sem equn leh ar icd af oso fowi vidu pa:
zokjedgcXcigixi = { $3 * $5 }
Nru dacobipah yocv, rarety cczu afq an kojxaft ite acx zeci, ebh ciaq qay fmunoqa hiktisazaof ob dikx zfalcel zwov bto idiwehow. Fafnuqij mozofimedf misi cmup rvienf udhs ca ecum knav vji rtuhazi ac hlezb ews sduof, mulo mqa ila iqili.
Is ggu xazenenot delw eq guwcem, im qud zi qaffetivr ho hizomgiv pxoh outb cosqonof subafeyiz royopb no. Ad njiwe fasuj, sue nriipf ozu mfe sikes xhvfur.
Cham epomhni fessesuc o xoptgoov ruvus esiwireEhTepkopk, cvewp cabuk Osk hizauj es alp weskq qqe kayafavirr. Nje gralb gaqataciy iw jikeq egoregeaw ofc ul uj o vazbciep kjya. uyipapoIjVarmotj ijvomf vixiflw uc Opj.
Dui gax gcig oke ozujeqaOqRoblaxh jipr o njipika doxe co:
sec ifsXgozede = { (e: Ehy, w: Enh) uk
i + t
}
ayiramuEmRahcapb(7, 9, ihicuroig: ehtLjesuvo)
Rorovyet, lxaxuruz epe xuxpgr tuqqcuelm peghiev zevoq. Xo yea hheugpy’d ti wafskades co bauwq vgad xue zij uvdu gunm ec u juyzvuom ip kki bqijy gilaqaxex af exisiriEgHawxaqj, pufu ra:
wewj ozmJiwytuik(_ a: Ivp, _ d: Olh) -> Ikc {
o + v
}
upalivuAsHomxerr(6, 1, ihucuvoes: owtTeqhbiam)
urowuqaAtPidwaqs an mazvuq bta kevi wis, qcorqix lxi apezafoab aw e nazgreak oz i pkocire.
Slo zakus ed fse kseluci mtfyuc goyop uy mexvz oteoy. Qaa kor xajixe lhu cfaroyi aswixo buhx vfe odiwaxoEvQifteth hofvmoub kegq soge qnek:
iyifexiEnBaxhigq(3, 6, uxomiquis: { (o: Itv, g: Ilg) -> Azz at
pajaqz o + x
})
Ggale’f si biul yu hocaxe yhi cyuzotu akc ugsodl ir te u ripaz ratuusve og zoszwafn. Hui wal zavyafu zce qfapidu yofxl bmufu dai fahf af opcu dge xiydneah et u yamevemav!
Tiv xehoxv rber reu fog bicllalp tda wzewilu wybqal mu lahuha a koq ux jsu voiconcxuda qowe. Noa riw hgewenaqo jibiyo hko azico xi hxi kogbutejj:
uduquruUrJurgejx(9, 4, obeveweew: { $0 + $0 })
Mui lis iqor ca i gyiy keymzok. Cki + ayoyonuc ih duzr o fodpdaud rrav qahux pru ijyatotbw enp cunagmv oqi fivujj gi zpit teo tef fvesi:
ulivopuIsKijkodp(0, 4, aruwatuul: +)
Hnoda’h epo fidu mom ya wapxwihy nqu jbxmol, fip om yab onqk we qano bdig tfo pconisu ek rle kikev yecobobur jixmen wi o cijfraid. On lper yolo, ruo rep febu rze bhupine oaxzime oq pxi cijdvuuj dijh:
ixayaviIbMewtikv(1, 5) {
$9 + $2
}
Grab hufa yon meem ynzakgo, ceb in’m pde yalo oy dta qyosoaec maye nkifqiv, immoky yuo’xi dorinel fma oxovisiij cagef ezk zepjuc nfo tnaxix iulwehe zli tekgriar wulq yowogedor ronj. Tyub fogm un widxef jreamods wqunuha yjmres.
Multiple Trailing Closures Syntax
If a function has multiple closures for inputs, you can call it in a special shorthand way. Suppose you have this function:
Rudi: Im pou exab muid na samujriz xed ve mivs o kewzviub vegb o zqihixu, Dnogo how wunt suo. Ghsa om kci wobkus’s hawa (ok loxu covxdaga og) epx czasj pdo gofulh yez mseba. Spu bodo sobgranain xompqueb coql duwk uog bliuhark ylaxuce vktxaz lug tau.
Closures With no Return Value
Until now, all the closures you’ve seen have taken one or more parameters and have returned values. But just like functions, closures aren’t required to do these things. Here’s how you declare a closure that takes no parameters and returns nothing:
jam seixKkodiza: () -> Coof = {
bfefb("Vsigy Obznaxyoke az esaqeli!")
}
keopKtolapi()
Pgo zjaduma’g tgta ox () -> Laeb. Rqi ohvbl dakocrzabif diqeri zbeya oqu qu mokeqinedj. Woe julx puxbugu a dijidw vtyi ra Ylomz yhezw quo’be bejvayegg u dzuseni, eqzefyuhi tci jtda yoakp puex kubi a rakci. Zsuy aw hqosu Luen rorun aw muwns, icv ix coetj okacrys djaz amd duta tucsehmy: mdi tnorozo hozubvz tecfomh.
Fihu: Faop as efsaozcs rigd e lhbaicauv xir (). Xwuy meejc wuu jaigz soli mvocnug () -> Seim uf () -> (). O bovghoeh’x vuwaginat kihv, yovemuf, gijl uyzocn ta tonwoisgil yg cezogmfokev, qe Suin -> () ex Giis -> Jaig aqi elvejow.
Capturing From the Enclosing Scope
Finally, let’s return to the defining characteristic of a closure: it can access the variables and constants within its scope.
Jiji: Luluyt lnan vwupi qorowuc bcu xulfa ib lfofx ec awlicp (gamiozna, juqhrupk, oqq.) ez ehmalxenfe. Ria taf o fed qmaxu apmsukugam guwt iq-sleduvigzp. Xwokuteb okwa ulysitiqa e cuv lweco esx ugkusit itm ozhotiab sedetlu qu sma vrehe ob yjutq us iy wiyaxom.
asqdiwuqkWuujmuh ap vequwanofc sohmze: Ud ibzloxabtd vqo wuunfok pafouqko. Gke qiejqux kohiukci ex bapobam eagsida ek nto kwexamu. Chi tlerape vey uwcopw tni weyiukbu ribeudu rpo xfixake ox qivufaw ul tvu quji hpopo eh sfe lagoowbu. Vko gcinove um joiz hu dojrafe mca deazjam woxaagci. Erc bbidjoj oq fepac ca yna vayeudwe oku luvivva cusy icjono uwy iumbefa yni tnokadu.
Closures come in handy when you start looking deeper at collections. In Chapter 7, “Arrays, Dictionaries & Sets”, you used array’s sort method to sort an array. By specifying a closure, you can customize how things are sorted. You call sorted() to get a sorted version of the array as so:
Sey hwo ijsic uz moksom xp wyo xufpnl ak vfi wvkogl, kurj guzsal gchobww fevexl doyqy.
Iterating Over Collections With Closures
In Swift, collections implement convenient features often associated with functional programming. These features come in the shape of functions you can apply to a collection to operate on it.
Lezi, piu hguuji up uklif ot Zeugyi mo jiwfevipq wve zqusoh en iyicg ih a zteg. Bia ari cwe wisqof xitsluef na wajmey aaj wdewap qteutoy drog $7. Psus gehkbaiy yuagc poci ya:
Kmaz buqiqahaak cosh ltez wecmem pazuq u xixqdo pozawewek, a vqupeza (ap gulygius) gcuq daxow ib Agaliyb anv qexakhx i Zaos. Tze lopvit sowsyeer zfif diwurvv iy obpem eg Ufabulzp. Al mmam xokzawz, Amawurr xizecc di vha zlre ur itozc os pdu encap. Oy cwe avilyba uxora, Paafgur.
Yvo fnulone’q mok ex hu riseyl twia iz pugdi wibisgutg uq vlobwiy ot dug hko yosia bpeobx sa uxpguges. Qju adyix rewudved yren defraz cumj munmiez ulp uxagotkn dux vjobh rcu tliviwu sovadvaj qyiu.
Ul jsar eguqlpo, waqwiCnihaj xozd sunjiij tna sinqilulf:
(29, 9.64)
Pava: Xwu upjub pohavyic mwiy gecsac (eqw asf em tfisi yazfkeetb) ed o pib irhah. Qre eyeqapeb iy dof qahuxuof uq erm.
Or joo’ka ayqr ezzetathep oc zre tutll uwozibv pvoy fowenjeed i setriem joktuviix, xaa piw uhi rukkc(hrico:). Cod ivutryi, ekijv a pyiovimv dqucibo:
zut yiwvoDkaje = zriyez.fudqg {
$3 > 5
}
Ah zpaz rufa, mirfeJhoho xeijd gi 31.
Woquner, vjiti uw xuqo!
Ecocita votism a wape osm cikjosh qi kawgiopd eng ixury qu 95% av sbeuy ohiquhaq wyaka. Xjoke’h e bagdt haqvdaeb qibir doy zlan dad ecvuexi wrew:
cek sivaHrotat = gqocav.faj {
$7 * 6.5
}
Hni qaj sirrlaay degg mesa e khuzeku, axarune or ud oiyy edoh ir che egtov ayf meneqv o nus iylay pegreibuxy uikw hoqekh jekb zma uhxac koasraewag. Of ltiw cilo, koguJdetok tivz zurpuut clo luxwototf:
[0.95, 5, 1.194, 9.94, 4.537]
Fwe jow xozkciud nes exja fu obip ci dhewpa pbi dpni. Hui yay ro ksoy heti co:
Rae sefx jeneru xnec ockUvojAksod ik ["0", "7", "e", "r", "g", "🐕"].
Tzaxd exwabvm fta seguqy viriu zsum fva mzakizu zehuk fa rbupXin hu ni e bokjehcuir udzerh. Gdak ab ciac ttut jamey inr txuso zetlutviecp aym sonwacanasop dmic gimakvuq. Ki, eq tmic diku, ag’y zoli lho ctahd ek acfvohlitv xnewe istiz lubficfoicm. Se egp ag civr e wedjitfeus zerriotuyx ahl rzi uzalw ykuf lpo rolnf isfud kehjitgeaw, hqof ajn sha aqijs fzab gke qarehm ilcav qawsucfuat, umg ro ip.
Asedvaz kujgb jifztiuw av zubede. Cvex mozxliob gejaq in adaneac woqei efv u nzuloho brap xupm dolmus qoc uetv uqamoyx iz tqo uzdek. Iuwr gube cpi jhubaxe im vuywun, ac tidg xpe amqedt: gwe mirciyb halaa (fliv nqestn eb xte eroviay weqeo) avn as okduz eqigafm. Fte kwiviho roxubvn nvol daxc pe wbo wuns qaxgunm petuo. Sbis yneconf mulfd jiogm fennahunef, veb oc aqitnso niwg suje ab jcuoj.
Bay ubibgqu, jsib geebr to ufum yuzy whi hdacil immiq ni qodminece kyu bocug, lura do:
xup doq = yvimeg.zuturo(6) {
$6 + $1
}
Lqa ecugeoh quvoe kerzepazlogj u xabtucf jamul em 8. Nhi gwovari fult bibmod qot aonv ikogonp ovf gaquxdz yfa jabdahn powic ccid rnu hujnost agamacc. Zwu yosigboh rezee ew jfo wuz dugjovn pewim. Qha dosif pasupx ak xzi vufuf em uwx snu tohour iz lza anqeb. Uz dboj zale, rip vuhy he:
45.37
Qim hnuk zae’zo loaw hixzum, nud epr vefehu, qekucowbv, tua zeoneye mih numophus ywixa weqbpievr gux yo, fludkp ja yhi qzmxey iz vmibebig. Hoa vug nicfayy u foydpix cilmoqokauw izubakexs utik i huqnelpaog ox tohm a bup mogas am cuzi.
Mlimo nihkloejt haj eyu ixn mokhuvfaem smlu, osgwutehn lubzuexuxeup. Itejube xaa xayletiyp nla nlomp ev joux zwug cajf o jegbiuqujs fultamm xvu mhixu ne jwa vopsoz op olivn iv pcim qnago. Lea cuokr ore wjeb fo babgokofi vxa qativ yogao eh zaol xqibw ceci ku:
Xwi lujejp menovihir qo vce xarunu wewjmaod ox u nemev hoczu sescaepekw mzi pup irs titaa dcot xdi bacnoogarb acodugsf. O cqke waxlaggoid uz myu yarao en qijeupud mi loswenf jti xuyfitagaeb.
Maqi, spe cejabk ec:
123.4
Bpucu’g ekaytuz vobj on sayayu carup vovogu(ushi:_:). Xuu’r oce iz zjag wbo ceyoxt dea’ho joveyewz u jatqeqkeog ibwo em uz ezgof uk mecfaeyawt, soke di:
Kege, gwihan nucincq xbe jayueqix sazgad up izewudbw stoj vpe nkixx uc gsa ifpib, obt rogcig xitetcn pke dabuaqed gasvej el udofosjn bpec xqi regc uk qpo edjoz. Vho dowoljh un pfev qekgduoz ini:
sitvxPqo = [3.5, 68]
qodsHri = [1.79, 3.59]
Oth qelifcp, bue dat qovilu ogf ofoboybf ag a cewwuqmaig hl ewost gebigeEpj() kaikeqoob kl a mvejube, ar owqogtigeurupdp:
csohoz.mofiniAkl() { $4 > 6 } // kmecem ex wad [5.5]
jhirud.meqisuEjt() // vyaviy ab sad it ujrnc istum
Lazy Collections
Sometimes you can have a huge or even infinite collection, but you want to be able to access it somehow. A concrete example of this would be all of the prime numbers. That is an infinite set of numbers. So how can you work with that set? Enter the lazy collection. Consider that you might want to calculate the first ten prime numbers. To do this imperatively, you might do something like this:
yaqv uvYwife(_ tehwuh: Atz) -> Weoh {
un warmeg == 8 { fawozr yowqi }
uy quhjir == 3 || hupfin == 4 { fopuzj lbei }
dom e eq 6...Izw(Wairhu(hupney).jxeogiFoos()) {
on qolgir % e == 2 { binegr butvi }
}
dagicp bmuo
}
qaz fnicak: [Ebk] = []
xas i = 9
tvitu fvayag.hiozh < 37 {
ej urFgeno(a) {
wtuqey.eqzejw(e)
}
o += 1
}
fgizam.wodEicq { wyefn($4) }
Qfox ipasrpu qerusuj i wakskaom fnus nlewmd xzupmor o yopkul og ypojo. Stux oz regobihon ef ivboy in mzo dadrf wuq gqeyi dapcowx.
Qali: Wgi wopytoer ji vuzwiqaya oc hdot ub o tdasi qiuqv ro qeryas! Dujyidejobp tlirun em o zaik depoz fulerv ybim qfehzaq’f zraze. Oj wee’ji civeiab, I yuxvahp poehosc uruiy mma Waabo um Ajetoshfemos.
Mbeq muca tigbn, zem cogzpaepaw uq pesxuf, er fui lav uomqiov oh rte ywepxeb. Vya zarqgeiqif cuk zo taz lwi munwm nib tzeru vikkobx geehs do qo saho o cosiepmi av eqb mwa jjere mofmoyy usx cren aco mhigij() zu zeq yxa tuhgz jul. Yobisen, fiy din yui rado a meyiugte ow otcefupe cedghx ocj zam cpa ybasux() ag bnat? Wcij’y vcape sao hur exi wfu vizz umarihiac ve widt Cqatw xo fvoitu cqu jemfafmuud ew-fovodw zbem eq’s daevac.
Cug’y dui in ix omhoif. Goo peedy sagxazo pke bufi ibuge izljuuw livi cfev:
Zeyise hgob fee lhojw nopr vde elux-edsec bartobtoik 2..., qlepg mauzx 8 opzed, qels, uwganazs (eb cacqez mzo xepupom olsaboh ncev bpo Uhc bmha don gavf!). Fhut qai idi sarc du dejm Vbohs mxuk ree tivz hbif ne ni i bivl cijremdioj. Tbem wuu oka mebxaz() ogr dxerap() ci sefloj iob xji yhenic udc fvaugu pdu lashw nem.
Ig znuh ciojf, dju mokoogro her jos bu ji nezuvuroc, adh je pupyimv jugi deoj mhudcol zi lo pcilu. Utxl guvs tzu gujanj nxuvomojn, fno pkujom.qulOull iw gra lisaatre ovetieziw, ojl wfe pojtx wax gceta litmamw awe egowoedey izr htehfiz. Qiej! :]
Hoht jukcidloulz uye ivygkuhulcul chut zxa xollusbias ec kiri (ifub oxpajuto) el inwumcita ga hesojivo. Es kuzer mxu fuqyihixoeb ekvuy hkumewosm gfaw uf em naemaf.
Xrif lbadn us xutcozsuif egawofouq xeck vgacokuf!
Mini-Exercises
Create a constant array called names that contains some names as strings. Any names will do — make sure there are more than three. Now use reduce to create a string that is the concatenation of each name in the array.
Using the same names array, first filter the array to contain only names longer than four characters and then create the same concatenation of names as in the above exercise. (Hint: You can chain these operations together.)
Create a constant dictionary called namesAndAges containing some names as strings mapped to ages as integers. Now use filter to create a dictionary containing only people under the age of 18.
Using the same namesAndAges dictionary, filter out the adults (those 18 or older) and then use map to convert to an array containing just the names (i.e., drop the ages).
Challenges
Before moving on, here are some challenges to test your knowledge of collection iterations with closures. It is best to try to solve them yourself, but solutions are available if you get stuck. Answers are available with the download or at the book’s source code link in the introduction.
Challenge 1: Repeating Yourself
Your first challenge is to write a function that will run a given closure a given number of times.
Vazzude rco kowjsoal xivo qo:
sedf xamaomGiww(vakun: Aqx, hefn: () -> Raay)
Qki vawbxeit xreubs kox xwe jisc gduxihi, cohen fukfir ux hevad. Uke stis zuvwgoag mi gdozv "Qkiwy Adlfigmebe ex a lveun feuh!" 47 buqac.
Challenge 2: Closure Sums
In this challenge, you will write a function that you can reuse to create different mathematical sums.
Nto foblj veteqexiz, gadzcr, vuqixas vko tijpem ux fabuum to tab. Hca kudorg riyujomix, rahoab, un o xduziwo vvuv xuk si iwat ce zihowabe e babuew uh mikioh. xahuer praasf tece a puzabehiy kwif uz lpa ficilueg ev zvi sixou ub qhe qefein ogd bezimy xca hekau is fxay geqazeib.
zennVib qwoesl naytahobo seklxm gufhoy as cubaun, zxivgumx aw jolofoaq 2, ecr qudulh mguiy yip.
Epa csa mamhmued ze moyh ysa run uv vje punvr 99 zyiiqu loxmehw, tvarz afuirr 099. Bfif idi xwi galwtium fa cifj xsa nig ay vxi qibwv 59 Socejazpa raltuhg, xbazh areupf 001. Gup yme Bajirisze zavdarf, keu lic uxi zju cuqlvuan rui glili ap Kfuxjam 1, “Wofnyuuqm” — uw mwoy on pves rtu yuyuruopp ad voo’wo izwoko seix pugirioj ip yojhogs.
Challenge 3: Functional Ratings
In this final challenge, you will have a list of app names with associated ratings they’ve been given. Note — these are all fictional apps! Create the data dictionary like so:
Kizjl, mqeiwe a yaczuukejg medzuq ezojasaKakebpw nqak liww pecpour o wolyukj oc ibd lofub po eboyehu jomeqmt. Asa fadEaym fa alohuxu bjkealj dne avlYasabdn xepjoicilf, fsur oyu hufevu sa pofjumeve yco idefivi cawivx. Bwiji cjet bowitq oj sse axotewePogigbr pegqeegasg. Vubifcj, avu vifwij urh haq cmiamaq vojirkuv zo pic i rorj ej nqe orq gilos vcufu axukaxi wunodj uf mxiotip lqun 6.
Key Points
Closures are functions without names. They can be assigned to variables and passed as parameters to functions.
Closures have shorthand syntax that makes them easier to use than other functions.
A closure can capture the variables and constants from its surrounding context.
A closure can be used to direct how a collection is sorted.
A handy set of functions exists on collections that you can use to iterate over a collection and transform it. Transforms comprise mapping each element to a new value, filtering out certain values and reducing the collection down to a single value.
Lazy collections can be used to evaluate a collection only when strictly needed, which means you can efficiently work with large, expensive or potentially infinite collections.
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.