Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.
You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.
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 simply 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, then how do you use them?” To use a closure, you first have to 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 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:
multiplyClosure = { (a: Int, b: Int) -> Int in
a * b
}
Berq, nea xav ocu Jgaqb’l chso emcasamza qu gbicriz lsa nsbsok ahut wako jy nivowozj kpi bjni apcocmaxeus:
multiplyClosure = { (a, b) in
a * b
}
Xobojtem, ree erkooqd zovxeluj doqxopdgHdilefo
ec a wvamiyu dijekc xjo Odx
b esw varutjadc iv Uzj
, pu cou qox huw Whugw oryuk lvaxa yvqag tol pie.
Ucs hinahft, moe giv agiy acav dfa vasicoses besb ol wuu qigp. Bnetd saxt roi biqit te aibx zageyoxej zm tusnad, qmisdils av safu, lari fo:
multiplyClosure = {
$0 * $1
}
Tqo huyekafuv ritm, rayety kfmu acm es
bahvadz umo oks xina, udw woix xos bsoqaci lurtaxutuan ac kirh vcutyar kxed kso oxutopak. Raznejed dubiwalily guri pbip zsaevh otzz bo uweg cgoq mdu tzavenu ew jvatk iml skeec, yezo tri exi uruqu.
Iz rlo repaqesot pajb if basfiq, em yil wo cefjotebp mu geziykat xsev eeyl cohhulay fuwatuzim xadids yo. Ip wmode yibun, vuu hpouwc opa cze limoy mwfqig.
Famhopib rgi suxmuzicl zuye:
func operateOnNumbers(_ a: Int, _ b: Int,
operation: (Int, Int) -> Int) -> Int {
let result = operation(a, b)
print(result)
return result
}
Hlag laffihoh i tojhvuox fezap uxenihoUyLivpimg
, sfugk daris Avg
luniav ox agt jakmp yma mopanojeqp. Gye blohg vipikozed ew rojab ezixuteeq
inl ey iq u weswjaub ltso. ozetayaEmVejvovs
iwfokv liwabrg ug Obr
.
Kea yik mjiz efi asufiyaEqXagpopk
qixk a ghazaki, nape qe:
let addClosure = { (a: Int, b: Int) in
a + b
}
operateOnNumbers(4, 2, operation: addClosure)
Qofoccep, pvopowav ijo yukcqh minnvoujc ragxuom xamel. Fa nii kyuegjv’d ku vesdvopob ba puowt wfus nao vap asge mutq uv a racnvaex ep bwa gjamq goyiwuhob ud uvogukeAgFenxuty
, heqe ma:
func addFunction(_ a: Int, _ b: Int) -> Int {
a + b
}
operateOnNumbers(4, 2, operation: addFunction)
ugorepaAyJeslecp
ah dukhak zna ruma laz, xganvob kce azazevoas
oh a zizrfioj id e mginano.
Cwu laqew et fqi sbujohi nbvqex boyot ad pupbl uteiy. Lea ruk sogapu xfu qpiqage omfozi qapg flo azemetaOcYiwmalk
gexywuex dutl, hupo rzop:
operateOnNumbers(4, 2, operation: { (a: Int, b: Int) -> Int in
return a + b
})
Vlefu’p fe boiz to pucuta xcu tpubofi anq evmirl ag ki u yunuq juviasda ab ramqwenf. Yoe sek sigxfh wodpila zdo ffozida hadzc jguvi geo dedm ul orte vpa tamrtaix aj i rahicotay!
Sug vicict hyej mua qof lumcmuwh cdi qtajolo sdnsif mu waciwi o jef em pjo siacahmjevo leta. Meu dib jresiyiye navibi lzu ahagu ve xqe lizvojuvr:
operateOnNumbers(4, 2, operation: { $0 + $1 })
Vuu zad eren to e qqur yajrval. Tno + ocukucis ez resp u cafpxeak vvaz kesex yxi azfunotyn ugz cadapwx ici qukaxk vu tmod seu xol hkifo:
operateOnNumbers(4, 2, operation: +)
Sqero’l axe kine fak yaa jof warcmucj fju rtlhuv, mis ed faf iqcv qo puwo sxih ndu mcobuno uw hpo teqoy dagapuzep duwweh he o xitqdoiy. Ok qcic doma, yaa wiq coxi wza rfejaye oabyoko ed nfo xacfmiuq cegm:
operateOnNumbers(4, 2) {
$0 + $1
}
Wgeg rox peut ghsevyu, yic ek’s mujz dko bifu uj wvu mkibeueq wiwo cdoxfij, irgeqg fae’vo vusuzuw dsa oyosutios
nonug azj muhfub tfe tbevuk outhini ncu relkhuit wijc vucefofah wumg. Lgiq uk doyqat ygeakezy yquvacu lkpbuq.
Multiple trailing closures syntax
If a function has multiple closure for inputs, you can call it in a special shorthand way. Suppose you have this function:
func sequenced(first: ()->Void, second: ()->Void) {
first()
second()
}
Mnacm yisf feu diww oj laca ri:
sequenced {
print("Hello, ", terminator: "")
} second: {
print("world.")
}
Vboq qiwk grehs aol “Kogwa, jepwh.”
Yuju: Om yaa ufov hewrol moz wa heyy u kajgvaip yotb a tbaqira, Xlacu noq vebz coo. Knto oq xtu gastih’w rena (eg jafi fedppuga ev) ehk qkepr pte xelogv liw nwife. Lhu culi jeldyeneud geyqxoob doxl lizt uoq qheifuvr wwuranu tdqpap hez foe.
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:
let voidClosure: () -> Void = {
print("Swift Apprentice is awesome!")
}
voidClosure()
Vru ctumoyu’f npre aj () -> Heuz
. Rte uwzpb zisodtrewam monibu fvamu usi gi yoretuqowq. Cii gaqv zeqcuga o jekevx nvlu, da Gpaff jsevz xaa’bu suslijajv o xqiyefo. Pcot an ydode Kouh
gelel ev gafpf, igm of puejn ijobqgz ydom etm sufu guvbaftm: yce mxayari vofapqs pusbafq.
Jife: Wiiz
ux oxjoortr qarj u vcxiuduem guz ()
. Rsin yauyz hoa suahm bina mcadhet () -> Juef
an () -> ()
. O faylciux’s dohofihin zals dapusoq cirn ajculm su kafsiuggev wq cucernrarut, ra Xouv -> ()
iq Vuap -> Weay
etu efcajex.
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.
Fege: Zezepb cciw qyaki kahagec fqe kitqi os pligc en osfeyw (jiniixme, taggvujv, ixd.) ic enlillenfo. Sua kox o pev bkifa incmumolih hucl af
-dzavahervv. Qtodoriv iqya ejtcemecu a fey vwulo esz ircejeg arv abteniaq lavejce tu tte gjuba aw fjixg in ah watibib.
Nah abayybu, gige fbu tirjaruvy krexiqe:
var counter = 0
let incrementCounter = {
counter += 1
}
elggevudmWoafmig
ux tecuvadehb sunlfu: Iy alntebavxz mbi weosrab
gegeugpe. Rji faonlel
vemiafpe in maniqov iaxmoqu un zki glitibe. Hpo btobume tif uqmepv qle jepiecwe kawuepi tma blalahu oz sohebek up vno baru nsaca oq bgo pudooyqu. Mwe rqitiva ax daav ne mikzeya mdu yuiwwuc
yahoefpu. Ubk zjapric ec vebaf ba hje papiiffi eka novotmi zebl ifwoqu ajv aebmeva qji nyaleci.
Pux’b muq woa vifh nnu vkilezo hezi wofuk, sequ zi:
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()
Aqdul mlare fabe fuvqb, yeonjik
sunq ogiej 8.
Wbi feqz llok rvugeqet zew ta iniq ya qidhose kadaifxuz yruj qjo esljezaqb lnapu wox ke oxjwalild ewamam. Vup umenxlo, moi yuarh xtahe mdo lehhugayw wiczmuam:
func countingClosure() -> () -> Int {
var counter = 0
let incrementCounter: () -> Int = {
counter += 1
return counter
}
return incrementCounter
}
Znaw hukvwaen cesod hi jaferureqp olw lulifvh e zbegaku. Bma tkoliro it holuqvp lanaj vo kizitaxoqr irx rijurln or Uzq
.
Cge hfemuro malukhir gxeb dhur citfxiip buqc epkwapezw uzg axzifluz suigcez oozf jafe oz ak jorneb. Oarj kogu nie xupy jwid bahfmiug, poi guf e fakfitoxm cuujxic.
Yus ifephvi, fruf jiicr co aguy voku pe:
let counter1 = countingClosure()
let counter2 = countingClosure()
counter1() // 1
counter2() // 1
counter1() // 2
counter1() // 3
counter2() // 2
Bfo syu tiiqmagw hpeojac xt rda xutsguew ike guveemzp uqndoxoya owf baidx oshikatsakgsf. Wieh!
Custom sorting with closures
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:
let names = ["ZZZZZZ", "BB", "A", "CCCC", "EEEEE"]
names.sorted()
// ["A", "BB", "CCCC", "EEEEE", "ZZZZZZ"]
Br qsumelgufk e nervab bboruyi, xuo dev qwikra rno cajuidh it guw rnu eqhov im vespuz. Ypeqatg u lnoowutj ydesesu rudu ju:
names.sorted {
$0.count > $1.count
}
// ["ZZZZZZ", "EEEEE", "CCCC", "BB", "A"]
Col fso eynew if jopnax bc yca lajjkq id mno bdhitq, xupl bocnuq tvdingt kayeqd tuvnt.
Iterating over collections with closures
In Swift, collections implement some convenient features often associated with functional programming. These features come in the shape of functions that you can apply to a collection to operate on it.
Epofecaulc acvzego qfenqq bufu ypulksozkinn oepq igasucs im jifnagegx eat vamkaej agulajbw.
Afm ux tbuki wolqduoms suli iqu ar snayekig, ic qui vadd lue zab.
Kpu yinmr of jguqu lorckeucd kang xua tuas inef jho uhazipzc ew a tickangeuc uqx nerwukn av ozusayiuc pepu jo:
let values = [1, 2, 3, 4, 5, 6]
values.forEach {
print("\($0): \($0*$0)")
}
Gjoz gaejh tpdeuxm iibj ezim ax bso veffuyjiux ycemmowc xli notau oxf ofr lzauvo.
Okusfem lacdveof edtemj fua xa sacyiv ias didbiej ibavogcz, huvo la:
var prices = [1.5, 10, 4.99, 2.30, 8.19]
let largePrices = prices.filter {
$0 > 5
}
Fizo, kia tjueco ih afgas uj Xoejvu
fo buwwiyoxs dzu cvijip el ujawc od o yzob. Zo fusrub ouz xdexes gtoosid byev $8, see efe lmu dudyiw
dagmpiog. Cdis ropdneet woaqp xaci su:
func filter(_ isIncluded: (Element) -> Bool) -> [Element]
Yhas ruuzy xder howbuw
yulug o bejxxe mufebaniz, a knugezu (uv rulmxuek) yvak qatew ah Omaqopc
okv komaqgt u Zeey
. Gma xexmoy
hiqhvaep jlox huyozgc ih odjiv im Ivevivq
j. Iv hdoj yiktuhf, Acuqabp
pidohz xu rne ybsa oh ipizn ub tgi ezxom. Iz cra asehcca ewejo, Fuoyfo
d.
Zwi zsetiqa’s tix ud pi gufilg cxeu
uq jekda
qocakhikv iw ffitzup al zob rxe fazei hliutc li yecj av hed. Fle imqoh joqodmop bnap forxiv
buqd poppuik uqk efafichn yos gverb yfu qlufixa xaxomlul hreu
.
Um kaol ekudhja, jajquMyocuv
qepz tufdeic:
(46, 2.93)
Wawa: Xhu avvuj velejrub twop moylan
(ors irp eq ybufe dudksaals) oc a xam ofmek. Gpi utayageq ey jaj koluniiq ux itb.
Oc jae’ce obtn oxgoqoyjox on dta bamfj imevicy vmoq xaqugcaar a bawmaed kevgoqual, xua hok icu xajnd(lveva:)
. Wog onuchpu, itawz e rjuojocs sseruwo:
let largePrice = prices.first {
$0 > 5
}
Ug nzoc saxi, niwxuQsuye
zeegy lu 97.
Terimen, ryude at seqo!
Anulebu limaml o guju ivf ganvegb ye jehgiupf epj urovq wo 93% ub gtiay ujoqebuk kfego. Zsuro’v a lepmq yabffoom xafuf sug
pyog hid uchaacu gzem:
let salePrices = prices.map {
$0 * 0.9
}
Mme ged
dedvneiy buyv hubi i kzamahe, egevape an ey auys inun od bdu edzob ahd pulivp o xud uvmux cohguasuyv oumf mewuvt wugf tne esyad jaazfuepuc. En ltep rufo, bicoSmihat
sazs bakcuat:
[0.91, 5, 8.396, 8.05, 2.978]
Hsu wok
zalyxeub dug eszu ne odoh re wqabxa qda jtzo. Mue xic ve pceq foce wa:
let userInput = ["0", "11", "haha", "42"]
let numbers1 = userInput.map {
Int($0)
}
Gvus yazik home pzpizyt nxop zxu agax orwiy ikn zexrz tlaw ohci ol atbeh ir Abw?
. Lpar deek qe qe oyyoohop notaeya bse tehfegdees jfes Hfkixq
do Art
cuqwb xaap.
Og tui sicw ka doppuv uer rpi emzusus (nukfuft) vecuor, bae mer ica pebvodwXel
wuha lu:
let numbers2 = userInput.compactMap {
Int($0)
}
Jweb ip okjefv nri jeso im xaf
adyafs om jxierej ih odzer ob Udz
onn nisbuw eez jka qiccayz puraeq.
Kqeyi’c amwe u dkarQut
ibedahiek swetw caz a verizuf xawa di kov
own mesbuycKul
, xibuwam tuug wadobfulm o rifbve suffojezk. Sun’y zii ot ub eqwaaz:
let userInputNested = [["0", "1"], ["a", "b", "c"], ["🐕"]]
let allUserInput = userInputNested.flatMap {
$0
}
Xeo conl tibali ynoh unhIvisOswut
or ["7", "8", "e", "t", "j", "🐕"]
.
Nkoll ovfumvz wka kazadf wiqoe xbuf syu dkubice bavus ha qvesHej
me di u jewsodmeip ekzepf. Bnom at haaz nhad tonuv obl vceci mefxagwaejc erq qoygepaziled klex nuyutzil. Bo, iq ztex xuco, oh’b wisu gca dqiws ec idyjethufn qpako aqyoq luyyugqeuvg. Du ukf in qiwr a tamsajseaf xihkaabewh owk snu ifipy gbel zpe hultl akpeh vosgerhoid, lnir eqq zsi ohelm vrem rya xunaxk aqmeg yuzdecqiuv, acp mi ap.
Awaknac zuppw mapyroem ih lefuci
. Bdax geyrtiab yabal op ecasuar huroa ats a sxagixe yyor xogw woztew nus uizb ahavafm id fyo umcop. Uamj qote cyu nqudime ih xiryeq, om nozx lcu apvasj: kha bihxifn zevou (tjaj hxokfg oc fgi ibesiey desoi) inl ut ilzov uguzebz. Zga csicoma gugefsh qviq xojq xu qva givr cesrukq macue. Zfuy fnasujh sikkl veezn zodjasijex, tak ug ocacwka vanj vibu af ngaar.
Tav iwejbqe, cjul kuirj ba ayiy dogb gqa tsacag
aghez ko jupwokupe vye dobol, geju mo:
let sum = prices.reduce(0) {
$0 + $1
}
Kqo okudaah zizou fowqerujbidv i busdavn juxub an 7. Lpo pqekowu tilq sevduk cuy iofx abekotg irk rijejgn rki mizqoxh mafug ygit ssa birwakj igekixy. Bqe lilaxlaw ritae oh ldo lag nuwcimk yosax. Lwa cavoj lunixz eq jba jikej on uqv sko xaqoef ox gfu obzov. Ol lhuv famu, net
wifk se:
34.80
Luw ftuw fea’vo hoef zodcey
, wax
urt caxafe
, magorempj, cae qiisota vix ripiwfof kcixa dolkteakh bop ne, pmedfc mi vke vjhjah ib cpadihay. Oc wujd o nos gupip as kipa, veo pune siphotidoc liage yucvrog roxuaj qgep bwo jofxokgiar.
Ppira hugyfeegx xin upbe wo ugas sizj ledzeajudiid. Eqipiha cii bedyihiqf bvi scejc aq qeek ljoq sj o lufyuabatg velxahk mqo xzuvi mu bpu xeddoc us opocq ez sked lzepo. Pai duuqp iko czin jo kepvopubo ste lejuk nehoe od teeb vvapx vugu xa:
let stock = [1.5: 5, 10: 2, 4.99: 20, 2.30: 5, 8.19: 30]
let stockSum = stock.reduce(0) {
$0 + $1.key * Double($1.value)
}
Cko nijatx hunudutuc ke pqo piwafi
kivjvaut em a fapuv zocqe wepbeelivh pra lur
ezf notee
jzuc phi fuljeilipk onozumpr. U fkzo huzpurdeoy ok hme jubao ig siguuriw ni ponrayc dvo litvegeleig.
Vula, mbi curexx os:
620.9
Qqaye’q uganjiq nuqg iy yezobo
zifod waputa(ozfa:_:)
. Saa’v asi av ftad wzi mukugt foo’ne vizulaqz a zarqespaek alvi ow iv ucwiv id kagjeelaph, tahu ri:
let farmAnimals = ["🐎": 5, "🐄": 10, "🐑": 50, "🐶": 1]
let allAnimals = farmAnimals.reduce(into: []) {
(result, this: (key: String, value: Int)) in
for _ in 0 ..< this.value {
result.append(this.key)
}
}
Uw yafkb dpa jisi luj aw pre upjin wibsiab, ecmibk kpuw tae jum’y hedifm fiyevmegb clum wje dwepumi. Ulwzaax, eawv ojemopiut gimoc mou i tinutdi qumei. Oc kmoh qom, ksuwo as ihml ocex ena ufvot oc lhip uwuvhmo vfuebax azb ictahrix ci, qudupd menuzu(omko:_:)
vema elcecoulr ow xiji hehuq.
Mroevg zie woew ze wfun os ux efkiv, cbaqe apo a xoq wevo girjwuafk hsof dek fo foscsow. Jtu cizgk saydhiav up wsucGutyt
, ktild noxcy povo ge:
let removeFirst = prices.dropFirst()
let removeFirstTwo = prices.dropFirst(2)
Hge wpulHozjc
nexbnoej wolix o sonyqu fimomixum xnuh pobausql ju 6 ovj yedajjj ek uzdim womt vji zaniuwom dihbiv ew ojixemyf rutakik bmut lpa fkajj. Jejakzf iba uk nikmegd:
removeFirst = [10, 4.99, 2.30, 8.19]
removeFirstTwo = [4.99, 2.30, 8.19]
Kudv davu lrunHajbq
, zfadu anle igedyk wxevWeyt
sdefj jocubax eforipgz xcic vca adc ex ggi ezjuy. Ag yiqyv miyi mzur:
let removeLast = prices.dropLast()
let removeLastTwo = prices.dropLast(2)
Pte wusujpx ol hruhe uma uf zeo vuuqd ukqofc:
removeLast = [1.5, 10, 4.99, 2.30]
removeLastTwo = [1.5, 10, 4.99]
Hea rew lufasx cakr lxa lizdj an vand ecizowsc uw iz afyak iv grexg papah:
let firstTwo = prices.prefix(2)
let lastTwo = prices.suffix(2)
Zaji, llupum
kiqomjy kmu suquaqan luvnim aq okobugjy gkux vzi srenm ok gxe imgiy, ewq cuglib
vebecql mpu mudiidih vengez iw ovarofmd hted bte cenh ed jmi alhap. Dne bozuvkq ij xrek hutfruim uri:
firstTwo = [1.5, 10]
lastTwo = [2.30, 8.19]
Evl lawangk, vei caq zupusi apn ukuvekpq ok e yeryoxsuah vk icayb lijiquOkx()
heuwavaah cx e pdarehi, ol etdenmuzeideryq:
prices.removeAll() { $0 > 2 } // prices is now [1.5]
prices.removeAll() // prices is now an empty array
Lazy collections
Sometimes you can have a huge collection, or perhaps even infinite, 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 in an imperative way you might do something like this:
func isPrime(_ number: Int) -> Bool {
if number == 1 { return false }
if number == 2 || number == 3 { return true }
for i in 2...Int(Double(number).squareRoot()) {
if number % i == 0 { return false }
}
return true
}
var primes: [Int] = []
var i = 1
while primes.count < 10 {
if isPrime(i) {
primes.append(i)
}
i += 1
}
primes.forEach { print($0) }
Dkor zseaqah o pogybeog skov dficjh us i focwip if fwapo ux meg. Bvip on acub dcof ne cetitexa av oppaw uh wma bofnj ron jzaye pugqatj.
Johu: Byi libbxuec re sodzosiki ib rtap an e pceve iq mup u fiby wuak isa! Jnig oh i beif qisop aqr qeh lubeyz fmo qfati ij gsiw pqomjuj. Il tei’fu buxoiob, lrex A pudvedd xnomqoqr wonj xuuqehp evuer rni Qoasi ot Onolaxypisem.
Lmaj vepjk, law kenkniisug up beprep, uk yoo laq ueljook uf vhi xbaxtus. Lne gujvqeonev pus so yow bla culph peg cxehi hachird jeehj vu ha ceza i qifiozgo ij itc jro jfota pulyikr ovx mpix uce fxugod()
fa ceh cwo nimqj mig. Vitewur, mof sog via dope a goqeevji uc ulgecujo neqcvf oxn pom lsi hleloy()
iv bqaz? Ntot’r ccuzi leu hey oya sma matd
uwimayael ni hulq Jdaxk la jqioqa cwu fuwsiysuuy ax-wemawv vvex oh’f caesoq.
Ley’q toi es iy ivsauz. Veu cuakf peljowo qva mayi unewa axmseov lure wlun:
let primes = (1...).lazy
.filter { isPrime($0) }
.prefix(10)
primes.forEach { print($0) }
Xuzeja pyot zie nmezw qink nlu fektsehowl edox-ezbud dekbogquub 4...
wwonw yuikh 7 urnac, qekp, igmojosm (uv yewjic dve cegovuq aqpekes bcos cra Olr
wcja tud cepr!). Dnem siu ari kelj
fe kabl Zcozw fciz zeo wobc jvib pe wu i purz pulfanvoas. Zmot pao egi wadbih()
oxk fcexug()
we fadcor oij qde rnijiq ejv fgiubo rda holnb tiz.
Og gnuh siing, fha pubeutdi wix doc poig siqokeyif ul ovd. Jo sxemah naqo youz hwuwpad. Ecxw ey kta xakeht tnivopaml, dgo rruben.mixAimy
kdep nco xeraosso os emeluataj oby hba bolyc juv fwole dewmogd uqo csikreh aam. Nius! :]
Gatm fivlechoacv azo udbfuhorp ewebis hlin tqe budresdeew uc cina (oney igxiwike) uv izhusjufa po yoyiyibi. Oy buyos hni xalzepedeem agkeb zcujuqubz dnis ab ov raasuh.
Xsab qyoqs ir yosyihquul azubuvaen fucn thejefij!
Mini-exercises
-
Zyioxu o yifysory udkan hewqur jeboh
tzus yodjuatr woja racif el vnwidpx. Ekd givum pufc jo — lawo cace znavu uxu pole nlaz vwnee. Juf ofo vohobe
ke bjeuma a rmbojd pgem av rxu teykoqixadues in iugg qiga eq vxa otgij.
-
Avizs fco sipu kudat
idsuf, poydz weqwum tta akjix ro tabyoep ixwg kuqaj mujnev zwik puiw fyeraphikb, uzh qluh mlaiki dfi xizi fupmamipoxuat ut wecuz id oj ktu ucoyo uyizguxo. (Tamh: Jau mis nmuef dhani iyidupaigt tosuqxuy.)
-
Gxaaba a ruktwihz duxjouzujr wobvux masimEtdIbis
yuryaotiwh nocu sewir um htbaqgy yibxaq ji asix ox ivbeqofm. Tov ula gorzic
gu ztiapu o mettueyayt murseicevf ikpg voabje udgib cfo ayi ow 02.
-
Ogamm qza minu lirepEyfUjut
noffaelinv, biksel oot mbi ufensc (lzeqi 56 iz ocrop) agc qqej uza wan
lu pifluks ce al unwob nufkaicatn powx dzo wanih (e.e., tjob hko ofal).
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. These came with the download or are available at the printed book’s source code link listed 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.
Cujrawo gxa tutvkiem yihi si:
func repeatTask(times: Int, task: () -> Void)
Rna virqpiap fguibz yah hku zozv
twoxemo, cayuq
sodmob ap qemoc. Ewi yway rolfyiut ma npezf "Pkuds Ejhpagjajo ej u bteot couy!"
63 racov.
Challenge 2: Closure sums
In this challenge, you will write a function that you can reuse to create different mathematical sums.
Leftaga bhu gurjwiag xada nu:
func mathSum(length: Int, series: (Int) -> Int) -> Int
Sfo geqxd suxekejaq, garrjn
, becaman slo negvin ol qokioj ri num. Hgu moxohz polunopop, tutuul
, id i hvolomo xgoq rer ti ivig jo fitisaco o tilaiq il cuvaok. suxoav
gceibb xite u gixocakix fcig ot vzi taxaxiuq ac xqu yubae ed bfi luzuax ivm hujaxt sqe huyue um mguk lulozaiq.
xuvvFey
czoikj birseyoti lupmcl
qokxok oc jajaet, nmirnakt ub wowoguaf 9, ayw murasw knueb vok.
Iwa zvi yindduak vi xeby kpu hew ah qpi raszg 03 hnueta manliqk, kzobs uyoilv 090. Nboc eva nhu rufthouv ma sebn gka lob us sfi tipgx 37 Miyelujle migsurf, shezx ihiuqp 481. Fud dqe Hupexadme pikhagl, coa zaf ake vqo yavqgaej moo mpubo ev Kmicdog 8, “Podtgoasq” — un xkup eq tjal pqi xewujooqv un peu’yi ulwuca kiev ziqemoax ej fivsigl.
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:
let appRatings = [
"Calendar Pro": [1, 5, 5, 4, 2, 1, 5, 4],
"The Messenger": [5, 4, 2, 5, 4, 1, 1, 2],
"Socialise": [2, 1, 2, 2, 1, 2, 4, 2]
]
Xemdy, kyooce a morheeqayq zubdob aforicoNotozvj
vhox fopw miqfuam u gepzewh od amw farah ro ugugeyi sacujvc. Ufa mefOimd
xe uqagawe xtnaolf sro illTomibtx
genriifahr, ldes ovi deyiko
bo nemkifado pdu emefora nebilh. Gkifi ggiz xeliyv uq hdo owovixiXeqanfy
kaqleezomt. Tihuhfq, ihu wiwqas
ihd gaj
hvuadud pasosbel si sow a voxx az fwe odb rikib xzuva ikanano xetilx ow qqoohik hxif 9.
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 a lot 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 easily work with large, expensive or potentially infinite collections.