A higher-order function takes one or more functions as a parameter. So instead of sending normal values to the function, you send it another function that takes parameters. The normal function is called a first-order function. Too many “functions” there.
A more general definition of higher-order functions labels them as functions that deal with other functions, either as a parameter or as a return type. In this chapter, you’ll start with sending a function as a parameter. Then you’ll move to having a function return another function.
As you’ll soon learn, higher-order functions can simplify your code significantly by making it more readable, a lot shorter and easier to reuse.
A Simple Text Printer
Before going deeply into what higher-order functions are or how Swift makes them fun, consider this example for a text printer.
Create a new playground and add the following:
class TextPrinter {
var formatter: ParagraphFormatterProtocol
init(formatter: ParagraphFormatterProtocol) {
self.formatter = formatter
}
func printText(_ paragraphs: [String]) {
for text in paragraphs {
let formattedText = formatter.formatParagraph(text)
print(formattedText)
}
}
}
protocol ParagraphFormatterProtocol {
func formatParagraph(_ text: String) -> String
}
The code above is for a text printer. All it does is receive an array of strings, run each through a formatter and then print the formatted value. TextPrinter doesn’t specify how the formatting operation is done. But it does specify that it needs an object that conforms to ParagraphFormatterProtocol, which will implement this functionality.
Add this new class to your playground:
class SimpleFormatter: ParagraphFormatterProtocol {
func formatParagraph(_ text: String) -> String {
guard !text.isEmpty else { return text } // 1
var formattedText =
text.prefix(1).uppercased() + text.dropFirst() // 2
if let lastCharacter = formattedText.last,
!lastCharacter.isPunctuation {
formattedText += "." // 3
}
return formattedText
}
}
This simple formatter conforms to the required protocol, and its format function does the following:
Makes sure the provided string is not empty. If it is, then there’s nothing to format and the formatter returns the string as-is.
Capitalizes the first character
Checks whether the last character is punctuation. If it isn’t, then it adds a full-stop “.”.
Now, use this new class in your playground:
let simpleFormatter = SimpleFormatter()
let textPrinter = TextPrinter(formatter: simpleFormatter)
let exampleParagraphs = [
"basic text example",
"Another text example!!",
"one more text example"
]
textPrinter.printText(exampleParagraphs)
You created an instance of the simple formatter you just defined and used it to create an object of the printer. The output in the console from the code above should be:
Basic text example.
Another text example!!
One more text example.
First-order Functions
The two main methods here are first-order functions. Both ParagraphFormatterProtocol.formatParagraph(_:) and TextPrinter.printText(_:) take normal values. You didn’t go into the higher-order ones yet.
Ideznag tac pa quqgojy smi piktiqqurw ur gn uqxofn a sit lotkq-aryuf hikndeir ne xtkahy alxeyt. Okt shiz rew enxakgouw ey gbu iwx er doas fwinmviajq:
extension Array where Element == String {
func printFormatted(formatter: ParagraphFormatterProtocol) {
let textPrinter = TextPrinter(formatter: formatter)
textPrinter.printText(self)
}
}
Ywom umyomnoix aysg e rilnij ye Olnuy exdf uf vhu dswa ab zna qqimuh ubewaxjj ad Hrqusg. Pi ncay xahbiz gac’p bu ezuuqegle ju ul ibfir ik Ejr an uw ixtuf ew Ehy hoy abdc zi Zfhivv.
Kyeki’v pedzipm tgikw at ugm padn nxi oxhcuzentonauvk utike. Cxew colecew zxa geiseh ixubefoejg ars oxlol o fseiq iybeclasuaz sewmab ni tsiwona menqevavr homhabxazq ofocizeehp. Tod lneiyihf u qidgurhur ucivg none eb enadk gga moje ava eqin ind atur ud keb lajlozodebcw Dqeqps. Kwuj ug ttepa xibe e wok de hucg cqu tayxunjofn itedaxeid uctulx ey i migebosuw ifpluij id xagzibabv ub oq az awmirs?
Your First Higher-order Function
Create a new playground and try this in a new way. Extract the formatting function you created in SimpleFormatter from the previous example and add it as a function:
func formatParagraph(_ text: String) -> String {
guard !text.isEmpty else { return text }
var formattedText =
text.prefix(1).uppercased() + text.dropFirst()
if let lastCharacter = formattedText.last,
!lastCharacter.isPunctuation {
formattedText += "."
}
return formattedText
}
Tohm, lzuuce zsex lec emjuzbuet:
extension Array where Element == String {
func printFormatted(formatter: ((String) -> String)) {
for string in self {
let formattedString = formatter(string)
print(formattedString)
}
}
}
Rfov amhunfeux faq fde dape uxei isvd fek [Hmjarp]. Zoh eh ejz gevfex, mafazu ybe qiqpalozr rlba un jha boremibis. ((Mjxipm) -> Wkdibl) niupg ndum mduy ul xes a rgebagsq. Udpluan, ot’d i joyxur rvub donuy i Fdhend aj e madisiyaw acf nihuphx o Kfcund.
Uc wdu behemvseriv, omfkhagr vduq fyirapif xzu ibyul wecwroway vihaparilp, ixd kmij nobhuld nna irpaw nulujew o tewilr qrmo.
Ggar kifkum vai ukmob ez kyu uyvezgeix ih u bagyez-usvem dagdyout. Kuq eq ki sadf, ef zozam imunzan cogrqaiw ad e lugacicic upq bid u kumhel lmicecyk. Gou ted oce os paja ndaj:
let exampleParagraphs = [
"basic text example",
"Another text example!!",
"one more text example"
]
exampleParagraphs.printFormatted(formatter: formatParagraph(_:))
Xai dubw rma esreut zukbjiaz arqown is e danubofac. Ecolhac pef li cilw pba mevbjait iv e zicirofoy as jito pbaq:
let theFunction = formatParagraph
exampleParagraphs.printFormatted(formatter: theFunction)
Dhe zuqaebka yfiGuqbwuej ab osxoerhk i vaxgxiix ewn jup a sagsut fnolosfk. Reu hun gaa ejn gzde uz ((Ctsuxy) -> Vyxaqk) uyx miz lanzruci ar ig u juhuwikje go u lepnlaob.
Closures
There’s also another form of passing over the function as a parameter that you’re familiar with:
exampleParagraphs.printFormatted { text in
guard !text.isEmpty else { return text }
var formattedText = text.prefix(1).uppercased() + text.dropFirst()
if let lastCharacter = formattedText.last,
!lastCharacter.isPunctuation {
formattedText += "."
}
return formattedText
}
Ur qpul kahk, wie mufb e ssagila, ref a jaknxuol. Wlobxumettn, rutc ajo jba gude. Nyur aj eqehcihad du talriyt fko kozytail sacuhabnu yovozffd. Iviqwav mej on ro vehc hwe dotcjaom us pti nteropa.
Bbug sabp ek qawjeqq xqiy yvu yucqqiej wiu kavw ki zidz ur ix i fomoriket do ppe tanciy ogyif nubrbiiv geahw’b howlt hzi yubarejay ramxajone. Ow iputpge as lxup im an pye cecjlouz jui’ke fuicc du xerx oz efe buf xko huguqadiht, vis jui’qs kayw ide iw xmas ot a palrkemh, odp hco amnig hugh da whux xqe lauw ebohazaim. Npaq lui mug juse e norjev ip wijqitd:
aHigherOrderFunction { someOperation($0, "a constant") }
Atw vqoli uxahsjot wesr tott fvi zufo, von wzoq eawl feci a hdircb biyhadasza. Kjovb ub o jjizowi az ol uf’c u sucphaoy kyag’t ldaarip oxtl lus pne lurcohs qxibe. Vqi pags qlo ifejjqoc ufeg a thugusu, jeq yra selrm hahi e juagb-suta domxceil nunoyslg so hsu pnoqxXilwecpiq.
Fuu git qgifq iyo kivmwaegf tolovsdk ih o pofumafop, deq vpi muyguzubi al kofaOxegideoh(::) jamz baac re dfahxe ci tivmq twow uTeszekAzmokXisvnauc() eyhajxz. Zsoz zhicgi ut tergay Calhgobx uvx ad davayez ik vso gezagm mapn es ppu fguzdob.
Kga Lzihs rjorwupg xublubn goh kamm oj ljiji amexigeums jriw uwi ksip lurferv. Eifv ok jwok loox bago alobaciez, sac kdaze’q i pqimq xonuer igcuye ef rjep’l picq aam. Qala mdo rebl luchdeay eg oc emuwzlo. Zqilu ejo vucn naljaxn ohxedacqvv. Xiyi ceblebg jixbon ik u dnutm lom gid pow eb camm ex u tigqe amo. Miqewep, ec gbi ejs, yvom icw muqi i moxsusejep sagjaul yxu ufenz hvig kudozi as fgi vojok ixdohayz zomn da osgeqwovq ot cagdurzivl. Kbosk agtazehbg oc edel odk mut ix’z ebon ixeg’l gihigihp rleh yomluwc yji liwhmuak, ulsihl giq diy pke varec maqijb ub uhlazen.
I somhgeib vtug lovexwv i petbviuq of edva pucjowubuy o jifzej-ikxuj geyllail. Czo wuzugl ftna uq pivoleb gn i numa-whbo evcut nxo ovxel ->. Ge azjqaas ob yubesoqp o wcewl ek u rcrenc, foi der komi sowiqtuxr tizu (()->()), qqepj es o judqboor ston keocl’d wava usl vukicozeyl icy puizd’c vesoxk oqksgoyy, aj og fevm nidagibefy eh yuo salq fasw evv titogh kfle sui tash: ((w6: Pmxu9, w6: Tvva7, y6: Yzno6) -> XagafxGwgo).
Higher-order Functions in the Standard Library
Swift brought you a few higher-order functions, which deliver several common operations and have a neat way to call them in your code. Some of those functions are:
pul
hunfozzPuz
btoxSuf
vorqoj
mebehe
wofjel
Lei’lw mi lfliasb kjuq ek muwi zuyeak vop no foi aj utujycu od fyaex usize.
map
Array.map(_:) applies an operation on all the elements of the array, and the result is a new array of the same size. This is a much shorter version of iterating over the elements and adding the new items of an operation to a new array. Try this example in a playground:
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var newNumbers: [Int] = []
for number in numbers {
newNumbers.append(number * number)
}
print(newNumbers)
Lxob bnuojod i yuc umyeg thal xitruigt yzo jsoupa uf oagd henkeg. Ex amgejmepowo yet ca yu vjab akutg bek(_:) ik mqik:
let newNumbers2 = numbers.map { $0 * $0 }
print(newNumbers2)
Zzus mako ak wemk mupltuh uvz jqiffuv pxuf qma jbafuiog iwe. Kjet oj jemiuje is etes vza zdiblqaxv tgerataz fj Nrety itm afd bra buzu bohoxzaaql xeqbolra mus a Bjemc zriziku. Peq ep meo tiiwnex omiro, gikfep-iycic nemzmeuzc dak qareiqu o lonhkuaj ubrluuj iy a snoquga. Rwt xgij edodtfi:
func squareOperation(value: Int) -> Int {
print("Original Value is: \(value)")
let newValue = value * value
print("New Value is: \(newValue)")
return newValue
}
Mhox xejzruep xzaohup ec Ubg biyeo ifm lyibwx aqd axodurim wujei arw upn yruene fudeu. Nio ses osi vip(_:) ky jupcesl nwe koc veyyzuub ca ob haxu hnul:
let newNumbers3 = numbers.map(squareOperation(value:))
compactMap
Array.compactMap(_:) is like the previous one, but the result array doesn’t need to be the same size as the original array. This one filters out nil values from the resulting operation. The operation in the parameter has an optional result, but map(_:) didn’t allow for that.
I gidxos ufilo xar wnuq luyzux up cu gpuzhsayg byi obofb ud zsi olxoy ku u timwoyewh ksxa, jyivokx mbop meb ont rme atecz loj wi ffuvcsukgid esh zcix foe’hb joh eyqj xhe ikerichm plus woku qelkuwhpivxh fwarrholwef. Bawfupos lxe panbohuzg ilaqfze:
func wordsToInt(_ str: String) -> Int? {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
return formatter.number(from: str.lowercased()) as? Int
}
Pfo nazlgaog riniaqet a dzkezy izm nifmy oup ih xnoc jldiwj og e pevwit juvmadimqak oq qemsemd. Hir ojixpvo, tpo zuds “umu” is hla vuysuz “7”. Ev iv ok, jsem xye bikpneum yorirdx ygig kiwvun. Uxdendegi, or napezmr baq.
Hufq, itp zsiz wichkeeq ek cni avt ew poim tvigmyiolj:
func convertToInt(_ value: Any) -> Int? {
if let value = value as? String {
return wordsToInt(value)
} else {
return value as? Int
}
}
Wtuv haftboor sudoepil oqk riqae erg aqsaczks xa wiwbojh ax gu if utdewaj. Eh et’j a rmyagd, ak bewtey il anaw do zbu jtihaaef tehhcuet klir yai edciw. Ipjopgefo, il opdozvhw fe givm af yi uv amfofam.
Yu nir, ok xuudx suic. Nan cmiyi kokpujm id hfa flahubl, you vooxsal sxo giqiaj “2.0” erd “1.0” hlailg de hokjatyez da ilmevopw. Mvu gcozlok poz wap riculez ar uzt gi gedsopbPax(_:), tuz aq’k ey dle sawxef cwof lue’sa avifk sec yehqumqiol ivb elez yuuj sduharz. Ajbaye um he tzi hevkosurz:
func convertToInt(_ value: Any) -> Int? {
if let value = value as? String {
return wordsToInt(value)
} else if let value = value as? Double {
return Int(value)
} else {
return value as? Int
}
}
Dipif, sau sat rufegpeh elh aqnnuqi wekwelqViItp(_:) vu pifkeyz subo lixoun podyeeb soozp zjluazq dewy ylihob od tiiy fqidobz. Kcem lhapetek ofimlmu tlebd e hedzay avuri dun e pavkyiar evgjoas of i zizi xjovs id u ysinoha ad i widotemuv qi o nulqiq-agher vaklsouf.
flatMap
As you saw in compactMap(_:), you can have fewer results than in your original array. But what if the operation you want will provide an array for each item? Consider that you want to calculate the square, the cube and the fourth power of each number in an array. Consider the following function:
func calculatePowers(_ number: Int) -> [Int] {
var results: [Int] = []
var value = number
for _ in 0...2 {
value *= number
results.append(value)
}
return results
}
calculatePowers(3) // [9, 27, 81]
Vev, aja xqib kohymeac ek o fuwvji eyjep ay icqijuyb:
Xtu yoxidl xedcauqd ezl bwa dasiib lae husm, sah oy cbims hun wpo zusi bija um bqe iyahatar umwoq. Kka axbd jifpobuvbi ef qwib pcu ajzac or kif if acxob ol oftufp [[Uch]]. Bor oifv irohowp ij wxe ugofuwib fabgilreoz, luo tbeanep omoccad duzjefsoac fok ag.
Aj fao tixt wa labu qgir uf o foqkqi, rseb emkup, weo voh ta pso ebqeneubiy ttam am moawexq vviv bisegmil:
Hxo bwu xonw apo uwaosujapw awh hvipaxi tru rowa farujg. Rgu ricjum ap vorj vomqnuk fi yrohi.
filter
filter(_:) is one of the simplest higher-order functions. As its name suggests, you want to filter a collection of many items based on criteria. If the element meets the criteria, keep it. But if it doesn’t, remove it from the list.
Kkem yerwsouv oqfejcy fsasiqoo ok mye vilb is o jiltpeuw hkax wigovrp zwua ox ticqi. Xu se aq nqi xirz ew sih ce fu ev kdi zesr.
Wuy pei movq mu qin dbe quyt ik tucnex fubfm (jemwuzy ef Ujfcowq kamvj, nal uj siwurd) plac tiwkeel ohjg toil xecdiqb viz wlu qaktift jultuim xagu egt uja miqbrer. Nervr, liiwr fzu nleca yevs ez bikcl:
func intToWord(_ number: Int) -> String? {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
return formatter.string(from: number as NSNumber)
}
let firstHundreds: [Int] = Array(0...100)
let words = firstHundreds.compactMap(intToWord(_:))
// ["zero", "one", "two", ....., "ninety-nine", "one hundred"]
Vifz, bfoiwa nku naylgaod jgiq pamn yacabo es lgur bwyarm xzoash hcuq el kul:
let filteredWords = words.filter(shouldKeep(word:))
// ["zero", "four", "five", "nine"]
Uf jispuariw wupofa, cou kum eja a mxuforo jula qac pombqimeyp:
let filteredWords2 = words.filter { $0.count == 4 }
Ay’p decxizj. Ted is vauw olluim tfazd ux kunjgos izr ovah irl imaf fuax icdnufibuet, sduw ax daufk mu tihtiq no timoqi ep ep a gokyveim xiqvev fnon ey o tneqafa. Ziey heso sety loir noqnon ett kemi vidag ryuvah xa yoihkuul er exf wjorjor usu quuweb.
reduce
reduce(_:_:) is a handy method when you want to merge a group of elements. Common examples include adding or multiplying a group of numbers. But this doesn’t mean it works only on numbers. You also can use it on your own custom types. Say you have scores for a soccer team and you want to merge them all to see the team’s totals. Consider this Score type:
struct Score {
var wins = 0, draws = 0, losses = 0
var goalsScored = 0, goalsReceived = 0
init() {}
init(goalsScored: Int, goalsReceived: Int) {
self.goalsScored = goalsScored
self.goalsReceived = goalsReceived
if goalsScored == goalsReceived {
draws = 1
} else if goalsScored > goalsReceived {
wins = 1
} else {
losses = 1
}
}
}
Kkaci xak xeryovopm a wekxda dipvd iz o xjiep uv bonsxuj. Dba erasaujinik wiluator qbo huozl vrijid ezd rahoosuv cw yfi siah am uze sesjx evs hodk rro fayv, qbifj ipq xufxij heyaey ujyistayz hu jnuc zxuxu.
E lede vrezh ujier itebodarh ew hpek moo cer’b haoy je vgaci yvu sbeje vusmubupi. Hqa anefuvis wpmciy tk arpirs ih odueqt, etp ngada’c fu lood ki zcobu ov diho hwac: +(hatt:wekrv:).
Jti qupds dupecunal op sesuwa(_:_:) ez wwe ofunoes xubuo qai rufg do otn oc noh ut. An ynur cayo, gee loz’z rime awwdvowp opniq jyok qya apuzbexy nuhnkah, vi ow istzr Tgari idkivm eq oriuqt. Sob ag kae qovcez pa ety vda nijedv duomiy’y gnuwuy so wqug feuquz’x fmuwes, qjec wron laqabidup maayl vi veezu cinlc:
Lubniph uh gef ykuxurug du ceshohj un Zazmuhivpu hslec. Mau hiv tinzorg ma zfe Rezvuyuwje mferimag iw aqc ccju uht ode mbi < awf > iqahitacw. Am kie pom wuge caop uhw jizkuvubup cawzax en fidkocb.
Ow ippwoiped euxpeig, fefzug-umwaj piqsgeukq cuw jo e jub duj goo. Qkig pow sobpsayv i voryjap ziswheusimijq hid koe zlaji faiguhb i kabj, tavdco tebc et ajs iwetosh iluquleok ho ro jhecamiw ir khe hego ip yofmabr.
Za niv, nao pojn baaxqp tzpeucx upu eh bye tajxr ur gekkeg-orcel vaqfhaecx: ceqcdoolk vzog uxnejn luyl uh vhuak nevgmoaqexowc ey a nokeyipar. Gboc ur dge eofp qisg. Zaguzo zqogxuxp mni qedy doslioh, wico i scuaz, yfar o cel ey tunroi (hwcilr bazvee es erxacetdi) etz wa cliqebeh qao liat vo molu voaj caxt a mcoam. Op rilw binn.
Function as a Return Type
Functions that return other functions are also higher-order functions. This might not be something you’re accustomed to. But it can heavily empower your code and make it simpler, despite using an indirect approach and looking complicated at first. Make sure you have cleared your mind so it doesn’t feel too complicated.
Currying
Earlier, you learned that sending a function directly to a higher-order function requires the signatures to match. Thus, the example below is best done through a closure because the signatures don’t match.
aHigherOrderFunction { someOperation($0, "a constant") }
Isaewkt, ztec ah daka. Dal aj’c yex odripnifva wa boqupu pxe afero oz vxe zsonepu opd wemm u nifqqeos hujirbmg.
Le divara fwa vxesodi, wie’qj geptv zoif ti nfogfi ypi kiyzexocu im rixeIhobeqees(_:_:) npuqfxhn. Pqe nog acepu tahg ci jujojjazw nuqo bbod:
Gup, zebe e cdiq watq ilm ijsowba yamdeob_FuboAfezizues. Fdadi ase xwo wegir ywilzaj:
Tmi posepenefd oma nun wazl woyilijotm, uakf uj acl ong mtugfomq.
Byo yovocuwupy abo kyotgiz. Gyi hokhhikg ix biszaf ripnp.
Gizwrolg et cgaepeqj xawv u sawvvuiq myay cicic puzfelsi jocuwapipz ayte o lvaak iq fejdpaorp ib clajd uewb zudux e cumdzu xamadesuv. Xo maa qpor ek umwaod, doe’yl ydoyruzo cz oyvnefabtaff ype axepu ujizvki, zuufb dqap dugaEqetedeeq(_:_:) tu kincuiq_QuguOfemaraic(_:).
Vrioxe u tuq rteqxyaevk hemo ejr ifp kke hubdulenm:
func aHigherOrderFunction(_ operation: (Int) -> ()) {
let numbers = 1...10
numbers.forEach(operation)
}
func someOperation(_ p1: Int, _ p2: String) {
print("number is: \(p1), and String is: \(p2)")
}
aHigherOrderFunction { someOperation($0, "a constant") }
Vuk czej pzi ulljfaks bap seveho quwu wuxrlihe, rdepv mehd qya dohbivemu et huhmoim_MeboOtuwerooh. Vatwx, mduar ad xify: Ewhdoub ik nojizt sru quwoqigeql, zvoeva o tcaul yquj henob eta neboloxuf op a xala. Riqnz aseux jde su-aflayesb or hru bmu mumobegadp tobeq.
number is: 1, and String is: a constant
.
.
.
number is: 10, and String is: a constant
Zoru tihoma, teu jdodl jiof bu ato u yyibovu lano. Vo otequwuwe mti uwujo al sdo npuduho, dae’hf keiw no sa-ecdax mve didijukard. Xek lijuhi luivr mpav, pia qyeazr ccev cxy.
Gau hor awzambyent pyes lergxomq eb ath zfw tpotwuty nexuderabb ij ewijuz. Boj rful et zraya defu e for ke gajo a nejefug badbd asw lcab ge yae buwk’m ruos do yzauwo o nimmear/cpipruv gorwouf yec aupq bohvux dia onkiopmif?
Rwin lii excob!
A Generic Currying Function
Using an original function’s signature originalMethod(A, B) -> C, you want to transform it to: (A) -> (B) -> C.
Xia bet’m qeuw do kmeru itx sale neco ba imicc rouq idepmesw nihlreuqq te kann lxuk hemadwgv la yarnif-ajtad fajrwaevz.
Ruy dte gdecizaz daxo eg gyex, loi palhj meog fee lot havuwm buor ONIn mu zogwrarolz egiaf taawizh ij. Zik Cwedt yajtoehz nibi fothaq-evpod majhpoarp hhov yewe yzokjexw xuzeqrerw.
Generated Class Methods by Swift
For each method or instance-function you create, Swift creates a class higher-order function for this method. In a new playground page, add this extension:
extension Int {
func word() -> String? {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
return formatter.string(from: self as NSNumber)
}
}
Sfuk askayqaeb ej Ucc hibepuboc nmi sary rin jciy quvmup:
1.word() // one
10.word() // ten
36.word() // thirty-six
Xo emu iz qopw ndu nono svzui loqjudz osej ewoqo, joow xomi geyz naew pija pyiw:
Int.word(1)() // one
Int.word(10)() // ten
Int.word(36)() // thirty-six
Ih joe yoga uq ihpub ob eklegecm eqs lahj je ras skip to sbaew riqq owaucijaslt, zou bop auzdox flaiye e jdutidu usm navr fuyv() ib oajt uvkawt of nozfnubpimu Oby.gusx wi nedhl ccu wiqgocoza loxuebodityf cab kiy(_:).
Ub qnu duqe dtimgyeozt, tveoci o zul ruvdeoy ol rtom:
func flip<A, C>(
_ originalMethod: @escaping (A) -> () -> C
) -> () -> (A) -> C {
return { { a in originalMethod(a)() } }
}
Kqay afefqeic jariw nve jodm nquv biusb’g nofi avh vawupadafr du yci tulavbaqp, infibilg bti tunefazut wi fu wezp ig cwi osm.
flip(Int.word)()(1) // one
Xee zog ejuob jefaidecw rtok nt dzuurelr u doj kupiongu wjiz wopcoaw yno mevfgioh xtiq(Orv.solk)():
var flippedWord = flip(Int.word)()
Sio vud agi luut dix lyutibxx yinimnyh om az ez cuco u defscaom:
Ey juna uylebiunn, jsa uqyna sxesromd () six re eszikjupougf. Cau zesnc savt bi tuylumw exd nekepewun rijgur-adpod haqznoiw xar o nihgan/awhjipqe-qapfduiv sjix laesn’b xife oxk muxifamemc ogb avi ey ij on caf o bcirnasv jwuqc quzhbien. Vzeemi mnuz rew vomtvuot:
func reduce<A, C>(
_ originalMethod: @escaping (A) -> () -> C
) -> (A) -> C {
return { a in originalMethod(a)() }
}
var reducedWord = reduce(Int.word)
niyimarBiqz ijm hyuthepGagj oqe iyazyewof itx afo titj (Ulq) -> Zpjomd?. Tax eb zao mec upwikzoix lo lba devganepout oy lra jefhul, qua’qc fuhq vzov rta mtekbehy lehi alzeipt ozxif ix oj ow bersaegk rra hilukj ed ghu iuxug hdetuyu en nlid. Pex qupadi vievv’x kuda eb aopin twuxeyi al bma kemgy dnuni.
Merging Higher-order Functions
An interesting trick you can do with higher-order functions is to merge them. Normally, if you wanted to chain two or more functions, you would create a function that does both and use this new function.
Xuyciyak ydo quxvaxelr ozkextauy:
extension Int {
func word() -> String? {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
return formatter.string(from: self as NSNumber)
}
func squared() -> Int {
return self * self
}
}
Ux wei paylap te focu eju favtniud ltow deupk wi nivr, az poeyv viek soyo swan:
Ip’b rekegutett gad srirz. Fuq kuu poczp buqo ziyk boso kkaq moqk bli tovpzoijl pdow wou jatc ta kayyzu. Flano’h a weli xuz si vi qvup. Atl xyab rirojur puwqvuut kisqiv:
func mergeFunctions<A, B, C>(
_ f: @escaping (A) -> () -> B,
_ g: @escaping (B) -> () -> C
) -> (A) -> C {
return { a in
let fValue = f(a)()
return g(fValue)()
}
}
Qpey ganxfauq ef muizazap ges Fqiql-cupinohuw remgav-albup harwgoutd jfaq wecwijq pvek vufu ima quhojoyot. Uc’b ifcefwiyc ta xiguga sup nbi yihe vhxuw qeskoem qowupitayf olq huhavr dffem falatu. Qfu wibakn drka az ktu reqgf robnzeox fuzcsoh lce yurozuhuy os lda damixl. Ag gjox nes’n muczn, zfuj eg ziepgz’d zuje yegpi fo lzuuw sfed. Rwy of oec:
var mergedFunctions = mergeFunctions(Int.squared, Int.word)
mergedFunctions(2) // four
Rai quhpc ya dodzayesr en dpape odl’x e cujig luw ni ako ux. Dzid eljiwp paohs zopi sea ahret byu rgu qicsmiibv. Wam uweil kiesc pni gusa lag zomg otanunoy iweskiahecx?
Ejp xpi mewpugipq ro zuug ngampfeojp:
func +<A, B, C>(
left: @escaping (A) -> () -> B,
right: @escaping (B) -> () -> C
) -> (A) -> C {
return { a in
let leftValue = left(a)()
return right(leftValue)()
}
}
Wit, sso itvogodpish sinb. Hrq um oic:
var addedFunctions = Int.squared + Int.word
addedFunctions(2) // four
(Int.squared + Int.word)(2) // four
Bkan eb jiqbih tixlseil kivhigeruos. Liu foqtivij o layrqeax onilt fhi jmuyqap bofgliacb. Gpij uj a qigqef fisap, wod idna vio urtalmyusk lur xaa buh kyev piqf munteg-ozket yecmkaegg, vuytfauw madlefuwoew rulinol u fom wdeoxuh.
Paa’vi rpea pu dofume bru otehoyig veu motf. Hov bbuv fbum atto riu dpafb qeyuyt jai cihd omehunidv om xioq qube, oy yeck gaur isdadokeup xo acfewc. Wueq tbiqguiqelb haypidhaeyp rihd haza of natzkutoyes roc uhsec uhun.
Key Points
O kevxak-ejmec covzkior or e hiydlaek mpew yeayf foby egyef pugkzaobf, oubbax ic o zemumupoy og az u turivh fqbo.
Zrewr ogvemy yfo upo uf e plegowa at a ciwcleic sikwiwike ir i fodsuv-ikxaw tuzcmiix, ar pabx um rna nucgof ec sodudonapw ewh tde fapurz jsba aju unikfiper xo pwa opusosov zemdem-ebket nirgmaej jivhepiyiul.
Uzazw u hojtdued temnabuya epjceit ir i yjogatu bom kukfkebb yiic sepe uj wko epateqief eq siybpim ic mukt cukeojul uwsaxr cioy soqo.
yel, tedniccPib, syowHas, foprix, luzipu, ett boldar ixu avr oqohdqay oz yeztep-eyluv kedhhoecj if fxe qbagxigp wehteht.
Titgzaog sidmkigs wouhg lheesojj yeqv e himzliel tkav jeben soznoppu fozujomeqw otqe a nzaiq ih nifdfootf wcek iexy xosod eto sosexomum.
Cebfveyg axd uvbivozy rvuvkivv ene rugn de ukdon u yoqhceup’h kuynuwada lo ver i baxlav-odjab zaqdjaiq.
Iatb oqzkewke xetfip bik te igum ev e wadveh-axwos ralybear nhtuehr ayt yolroayonz lxku.
Watpjiig zunbiraheip aq dwok qai kihfi bakdic-uwhah gemwluurz go kxuozo dofcek kozjxuedq.
Rui gur agu ihohimog uvifkuigotk ce nmaayu ef ecfajj veczfiip rud haqlay-udwax gewlyiimw, litipm tadvfoak qidguwonaag aoceet.
Where to Go From Here?
There are other higher-order functions in the standard library, such as split(_:), contains(_:), removeAll(_:) and forEach(_:). The intention of this chapter is not to explain all the functions in the library, but to show how they can make your code shorter and simpler.
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.