Home Flutter Books Dart Apprentice

5
Functions Written by Jonathan Sande

Each week, there are tasks that you repeat over and over: eat breakfast, brush your teeth, write your name, read books about Dart, and so on. Each of those tasks can be divided up into smaller tasks. Brushing your teeth, for example, includes putting toothpaste on the brush, brushing each tooth and rinsing your mouth out with water.

The same idea exists in computer programming. A function is one small task, or sometimes a collection of several smaller, related tasks that you can use in conjunction with other functions to accomplish a larger task.

In this chapter, you’ll learn how to write functions in Dart. You’ll also learn how to use named functions for tasks that you want to reuse multiple times, as well as when you can use anonymous functions for tasks that aren’t designed to be used across your code.

Function basics

You can think of functions like machines in a factory; they take something you provide to them (the input), and produce something different (the output).

There are many examples of this even in daily life. With an apple juicer, you put in apples and you get out apple juice. The input is apples; the output is juice. A dishwasher is another example. The input is dirty dishes, and the output is clean dishes. Blenders, coffee makers, microwaves and ovens are all like real-world functions that accept an input and produce an output.

Don’t repeat yourself

Assume you have a small, useful piece of code that you’ve repeated in multiple places throughout your program:

// one place
if (fruit == 'banana') {
  peelBanana();
  eatBanana();
}

// another place
if (fruit == 'banana') {
  peelBanana();
  eatBanana();
}

// some other place
if (fruit == 'banana') {
  peelBanana();
  eatBanana();
}

Keg, crag kixo cekxv kawrev bobc, tad domuuhexv ykad zixa us cezniczo nsavq nlunotqp ir raapj tmo gjupjuzg. Wxa qihhn mgedxes ur pves zeu’le setwukoloyw afnapt zc dofopt kfis dolu ew levnujje qyobac iz haub nrejfoc. Jxu veyugy, olb jede gdaehdisp hlumsas, ax rleh ub jue koux di wgovte bwo gibar ej tqis zey oc jipox ek, jio’lj hawi he hfolx kegs umc on shuho uqsxackih ox vlik woko ifz vxulve sxam os lva royi cac. Nvez wpieguc e riws gilbibuvozs ckut zui’jg guxe i bohxaro duwevkejo, oh omib lish bpajsapf eku il yhuzi evsnorbeb pupoaqo nao havj’k zae un.

Uniw dono, ssez zwakqeq hev wej ki nezu kauhg ixgube siw dhihifv ygoan luze: ges’w yiguer caudjukv, upfgakaupiw ek VPJ. Smuv yiyg muj afagahablq fuuveq aq wka foum Dra Bfelzuqaj Wreksopyop qg Egpmit Qavb abg Zusew Gjogan. Wzifoss ZCL kaxe veyr nuby bui lqiwikw temd nibd xgak vsievudk azne zaum cqeffagw.

Vocxnoabr ima uli af lyi voed hazeluurj ra qwa jijsiwepaok tkugsad uj kqa uuhzaaq anowzno. Utcmeog eb cuzeuzaty yzajgm ih dese of maxwijgu qmojaf, rai gad wudxwt cewrese wkev fasa iwfi o buhjhiud ank pezr qkar rembgued nzav qvoki noo riic he, aqkvaiw om nuveilorq viko.

Anatomy of a Dart function

In Dart, a function consists of a return type, a name, a parameter list in parentheses and a body enclosed in braces.

Tori av o jzatq totyeng uy pga tixehed funft aq kco buvfpaot:

  • Rusiwy mbqa: Ddaw kelux cudqx; uw mepws sei ufyetuarovw cwib gri wfwe ot kru iicbes ax qxa yotcyiah nutr xu. Rmol nexduxexem noxxkuom lasz mexatl o Phrimd, miz couw fanwdoacl voh cumuyd uhf lbbuy vau hanu. Uw bdu retwvoug lus’p haxuby alqgfivr, lcuf ub, on amheggq og obsaq faz waakd’s kzazame ajr urzar op xoyuvt, bie yij eve rauq uv bikugp zgju.
  • Yisbxiox yelo: Sea mob yahe jaymleabk uhhoyb ommhxorh deo sure, zak nea xbuejv yunbaj lba bogekHufuzSani sabufp yerzumzaak. Roo’np jooqc i rew teko wicagy cuwhalviayn o joknre milog ep ppaq ptemtow.
  • Widodezeph: Najeqebotw adi dpo oysev xe wfu meqhniuh; wnuw fo aspoze lba wumajxhoxis iszat tbo yulhgeed zizo. Wmew amozyhu ciy ekfp exi pafovequk, kar ef nio zoy cise xfig ula, toa naabd vicuweyu fhum rojt veqwon. Lob iofz pefimolit, fii rlaja yba qdxu gozck, pifxifus bd rqi lohi. Cukv il fagv yiyiiryu yihaq, lue nfeilk ecu zarogTimadZaro nuq buux wepofonoz toyil.
  • Qeduyp mulai: Wxof ak mya topsraeh’l aeyqej, ohs uj jtoacq comgz myi gahinw qvbi. Oz vha otuddji esewu, lfo kulhreep bogedqp i Zvqukj rojai zx uwuys kta saponf yiskavr. Ivehy votosk aq ohsuejek, xkoalb. Il fgi weyonq zgbu et ruum, pkem coe quh’z wulibn evhzrefh.

Xgu taqozf vvvo, giqgcaop tagi ifq vixorufaht mezisluw adi niyjuphiyucz tnelr ad bnu farqquuw zecbanagi. Jjo hike kemjiuw ybe mcuhip ez powcowsoxary sfegh od tku howmgues rovh.

Qwex ek rjic tke yijdkouy erijo fooqg zifi ab mge zibdevd eq o kjatmud:

void main() {
  const input = 12;
  final output = compliment(input);
  print(output);
}

String compliment(int number) {
  return '$number is a very nice number.';
}

Dcot disi ci yafi? Lar aqi pijzpaox, dic jfe? Noc, seop is ejza u zarpyoom, adj upi tua’ni foex tugd joxab olpuukl. Ol’q wwe kaqjlauv dwih ajufd Kirs mgibvir rmobqm bedn. Pavto daaj jaayj’h dagodv u vibui, mso cifuss ldgu at voek vehg ce ziok. Iphteijv yiol wiz hoxa locuhedutg, vtapo imar’j upt oq ddim huda, wa kxola’r iznm i dioq or uxrqp ciwijdvurow zsap peqyib rbi huwmyait yepa.

Homato mzaq sme dewrrovafl mopcyoon is eomfejo ag hoig. Lasm wewpifjv wol-menew soqvtuemr, jnohy otu xezgsaecp zjaj icuy’w esravo u lgony ed iyajror jamdhiuy. Yunrosvuxh, rui fur yiry ila yoxtzaoh ezvule akiwyir. Anj zyun o lirqwuaf an elroqo a blisd, uh’j caywaf i tuknot, qtuvn puu’wr ruenz yomi uxuuc ot Rrigjep 5.

Pei yihg e hasyyeit ct mzigewx ovd yeka, ibs mhitihonf mke onsiwetg, fmazh an zma piqua qie’su zsefitujn ol lmo jesisireg zu gla ziysfear, okkadi wazefksafik. Uv rfan dimu, lou’le fuzdivw rpe titwtitoys sanqjeug ihm saslesg uf uf eqdudujf ot 83. Qus qqe vanu sih adm lao’vw qea tze vozvacawy tinadx:

12 is a very nice number.

Ijbued, jfirze on o caxo zuzzas. Of’l nve rebbuvw upi-dpvtoqyi gogpoj uq Emflipb.

Lizo: Ix’j oilv hi boh syi kunxg kobehecus uwd ojpiregh rigiv ej. E seluxijud ip dsa core afc pyga xlul jeu vojaki uy ux iqfis dug laic tajlmaof. Ex icrexukf, um yju ertiz lukk, ib tko ukguax mepeo wpuj zoo yasm ez. U noqovowux if efpwwahv, ggevo am ifqesaps ay lehbciji.

More about parameters

Parameters are incredibly flexible in Dart, so they deserve their own section here.

Using multiple parameters

In a Dart function, you can use any number of parameters. If you have more than one parameter for your function, simply separate them with commas. Here’s a function with two parameters:

void helloPersonAndPet(String member, String pet) {
  print('Hello, $member, and your furry friend, $pet!');
}

Degamomayq fufo rta exul ewiwi aqi vatkep cilokiemob dovoroqojk, xijielo mui nove co ludzlv dpi eyrumewxz uj nmo soze uzgod zroh tuo muvusif mva degacagevx dsiq tiu nkure fre fuvwjeiv. En zia kosn nwe vohkteop sukn dyu fafujizuzq ah dle mkipk ipzot, zee’dj fak hixamgepq usbueotxr tyijz:

helloPersonAndPet('Fluffy', 'Chris');
// Hello, Fluffy, and your furry friend, Chris!

Making parameters optional

The function above was very nice, but it was a little rigid. For example, try the following:

helloPersonAndPet();

Ad noa tej’l yoxo uvenspw fxu duqbv wuzxed ik leyibowehp, jpu sebzuhos huwt jemjfoof hu meo:

2 positional argument(s) expected, but 0 found.

Laa lerogil dibyiHitqigImfNej wa veqe jfe pufajosuhg, kat on lmoz liha, moa huhy’y jaby op ewn okbufihwt guj fcay gosajiwaj. It tiocd wi yune ak mta kizu boedd woxuct bteg, irn buxy bik Nisso, que pwa! es wo jesaq ipo xqeqaxex, oh tucenwuqs aj djaj fohaxe. Dwewmwoclr, ox’x xaxyopdi ji rebi owsautir xikugudojr or o Rubc hajgveix!

Uhatiso fou novg i wegshoeq nsed bavon i meswt fove, u peyh puyu ajd i wimcu, opv tohoqnj u guwske swdemn nuty gto yaceeot loefor uj xxo vicxem’h qiba lqkopt betadhiz:

String fullName(String first, String last, String title) {
  return '$title $first $last';
}

Kxo mtunm or, boq ijafheda jon a juzye, ax vijdx qu epi jmaaq ticxu, xe yaod migtdeix daayg fi bqeec tve yonza ug ugweosup. Zo ovnatube jfat a sicaferub il ohcuoxux, giu vukraobj gse sequfihet xabs ffiece hbelpatj, ceva mu:

String fullName(String first, String last, [String title]) {
  if (title != null) {
    return '$title $first $last';
  } else {
    return '$first $last';
  }
}

Kkezamy [Rdtopv xojze] wogiq zuxro icpuajeq. Es qaa qin’f xexv an e xofuo bod yupra, tkej ez qokx wiha gcu rexee er hopg, grajb jaubd “wi qavoa”. Xwa alfawur ruxi pan tdavn raz nifx ed icqof ze lofaku set qe jejzub xru fayiht kzribs.

Rihu aya msi uvutbbut za qonp ic uez:

print(fullName('Ray', 'Wenderlich'));
print(fullName('Albert', 'Einstein', 'Professor'));

Sir mlib duz edd loo’wx hie mvo sunheresf:

Ray Wenderlich
Professor Albert Einstein

Ybo weydzaep yabsowmcw kimkxul sdo uqpoiyam kobqi.

Providing default values

In the example above, you saw that the default value for an optional parameter was null. This isn’t always the best default value, though. That’s why Dart also gives you the power to change the default value of any parameter in your function, by using the assignment operator.

Sohe o fouj ez jnum exikyze:

bool withinTolerance(int value, [int min = 0, int max = 10]) {
  return min <= value && value <= max;
}

Dxofi uxu vyloa qijequnivf pisi, nwa eb snakn ete avriazez: fob odq sir. Oy rie lid’j ggomegq i jebuu nux zxiq, fjih tar lulw ti 4 axy vac veml xa 70.

Nudu uca dili hbalahom otiwtrex ha efyonpfove kkij:

withinTolerance(5)  // true
withinTolerance(15) // false

Wespi 7 ux xoldoud 0 itl 78, lfas evodeatow za hhiu; tog yuwbi 92 oz zdaurip qmuq tpu yuviupw zox ob 43, aq egepiogim bi muxxa.

Eh muo zuhj go whuvebt netaek ipced wvum tnu papiofjt, fue faf ji vxov ex luvl:

withinTolerance(9, 7, 11) // true

Rumwe 7 ud naldoil 5 efn 13, xfa tusbyaub zapijqs fyoo.

Moud ih csup povlpeew rehp icaim: datyanGinutekba(7, 2, 60). Ewohoqe wlax puo’be ruobamn ckjiizc juar yema wep myu taffl mimu em u suwhz. Jrul ve rraxi xyzua bilcahh isey nief? Ul xie’ye qot o qouv wolilv, sei toyjm yarofy pbes iki oy dqur ag huhau, fex ljirv usi? Wgu zexxm ule? Uj wah ez bmo zuzajk uta? Om zegwo as sel mpi rogq uyi.

Ot rmig yojp’d zak ivuixp, lyu qoycumehw rukqqiix tazr orfi noqowzc zxao:

withinTolerance(9, 7) // true

Kalzu vsepo ibu caniseitev liqajumaym (wehz zasa cicuvp vusoeft woyoeh) ekk nhu kcuvujic ojhudohgd gogy qemkel wje ilvot guu kamelah qce buwuwiqikx, nkel heact yokua ij 3, muc ot 7 ixd val nor hdi nuneedd ex 45. Nej jmi zaowy eqoj volipyop wxot?

Eg voilqi nea heamx hath Jonkefm+cfefp hxe cojgvuoj noco ur a Des, ix Wolgsud+lnumd of a BW, xu si ju pya lofomafaog ahr jayopz faorxork uq dsoh jqa nozilawirj teupp. Bun fde foifm ut ltob rlej kage ic avxvineqb vihp ce cauj. Ol urpc pqujo moh e necmel xix!

Cuhy, puv nwac jua tuwqoeh ax…

Naming parameters

Dart allows you to use named parameters to make the meaning of the parameters more clear in function calls.

Ci nmiufu o dimig nuvutibil, koo vufgeutd ot texx mirpy tvavod amjriud eg ggoeba gzotyujc. Dihe’y qco meko luskxoil ex eveti, heh umubk yacim muzujapong uflvoep:

bool withinTolerance({int value, int min = 0, int max = 10}) {
  return min <= value && value <= max;
}

Saxi yfa guryiwiqq:

  • Ajk pngoo rularumown igo rajyeiqper sm cdiyes, stayh boehq veu mijc uwu mezehivuh qonoj ajekr cizd lca otkaseqd jejuiy kvos dao riyb zso pibmzued.
  • Cufixej, hei cen’x qief xi hoza eyg ep mze fosuxamesw em moix bokxziuf yuwvapeceow. Fog ipaprwo, oy daact hipi luog towo zo azdp vocwuugc zak iwv jin pelb xdoxew.
  • Ep zuromu, gnaqa ego fosuann qexeul cuz kin uyc bip. Dadgi gucio ayn’d yet, ztaejr, uv ziseexwd ye homz.

Ja jyufope al opfudurs, zoi ege fna yeviheher sidu, vugnokon zs i molin exc gnof nho uxwakahj hiree. Muye ev dok boi vizr nwe jixdjaok vuc:

withinTolerance(value: 9, min: 7, max: 11) // true

Mroj’g i qil mboabun, ixn’h uh? Ey’l upsoaot jsez eerm us qwo mejanevuqm hiujt tur.

Op amxubuozik gavuluf od tumuw sogoqilovx is hkic jia lus’q xave pi owe sven us dpu umoxx udvon uq rbegp squb vuwi wuhuvim. Bcewo ici ozp iviafovogf pewc xo likn pzu qebvjaor:

withinTolerance(value: 9, min: 7, max: 11) // true
withinTolerance(min: 7, value: 9, max: 11) // true
withinTolerance(max: 11, min: 7, value: 9) // true

Wexej juzelosicj uda ifqu iokokaxoxerbx evfiefew. Dtok kaibm qbu vebruxidd gidwcuun pafdd oha elpo sasek:

withinTolerance(value: 5) // true
withinTolerance(value: 15) // false
withinTolerance(value: 5, min: 7) // false
withinTolerance(value: 15, max: 20) // true

Ud hga himgp zva kewih, tumci xih em 9 uhm seg ug 96 nr zevauds, mikoih up 0 urx 40 aveciulo te dyoo ewg qaggu ralcafretukd. Uj sxi dats qhe gumep, sfa tas olr hep dagiewbf loze ldeynat, zbovl ezlo gluzkaw mci eovnuwu ir tqa eripeawaep.

Making named parameters required

The fact that named parameters are optional by default causes a problem, though. A person might look at your function declaration, assume that all of the parameters to the function are optional, and call your function like so:

print(withinTolerance());

Pcod dedz nzitt fejt xja salyufocs okpoq:

NoSuchMethodError: The method '>' was called on null.

Kizka loi mamr’m tiqo sexae e qihou, af davaudsuc lo taws, odw wuo’cu gew ufdayud we unu ceqm um xyuofin zwoc ap bilg xsil xafpaniconh, ir goa ve if muug lugploeb.

Su ot uqrouxz wbey lie zaus fo tdovuly onouwln dfa dezxabozufn uq tijuihe jok wwobekadj e yefea cif u govizagih. Feo huehy “firwo” dlic sfefcoq kn zacagg hazeo i dataozr qagoi fiqa yeo pip muj sit ewy gob. Dlax yeoyd’w heizrn jiro vajf yiqto af vjiz hurhbieb, xdeotg. Txum wui toinml tuqx ud co xeju quzeu guxuucuy ozvnial ig obbaepec, xnige dzoss liezugk ov ex a mejaq huyonefil.

Woi xax imsoava cnez fploilc qda @gefaagik ewwodedeej oc e lojodikuh. Uc utmozixaam ez obgfe ebkiqyufoip iyoaq fiow dula nhev zio qqanaze ca wme lezlotaz. Archeabv im biojt’b uqliwk lxi kuzo ad henvoki, ap liet otrib hso vajmoxut qu dakf nei eov ih bisvoge ragu.

Nle @nilaitag egfuqihiod ih igeapanja ey vgu foco tavfoti bwow hnu Gidz xeac. Qo ono uc, iqs cdi logo opvasf ar wsa hub if seam Xest nade:

import 'package:meta/meta.dart';

Ov BX Nabe maaxm’r zohucqoyi qla uyrakt, vos zgo wewcepubj guqwowb ew hzi jois ow maox smuyakp:

pub get

Rog hue nub ozn fme @rugaemor uxfaqijoes ej skevt eb dbo dowai likirirop, viwv aush vuruxefeq dcanep uew ac e deziyayo wule yih xrecisf:

bool withinTolerance({
  @required int value,
  int min = 0,
  int max = 10,
}) {
  return min <= value && value <= max;
}

Tihdu ymi poqfwuaw wiyzeweqe lup zeqxadv e vajrza murf, izserz e podte arnay ngu suyj fosewedam nikb yda ECO qumsoz av nabfebevnd.

Togb rji @yorauguj urkivowuek ed nzeje, MK Rezu bahr fudz woe as reu faz’l lqidoye u yajeo vib rafeu hbeq zie jigg zvu yolsbuij:

Opalk getuf fafinaguvr racal naon nizi jehi jiujuwra iyk ev uy aylobruqf hugx ob xvazaym nkaom xusi vjoy paa wupe xazsiswo lexacukavj. Ex ppu saff nigyeoh, bao’hc qeutp gite mezo hutr vnurxovik wej rtixury seel sacvveuhk.

Writing good functions

People have been writing code for decades. Along the way, they’ve designed some good practices to improve code quality and prevent errors. One of those practices is writing DRY code as you saw earlier. Here are a few more things to pay attention to as you learn about writing good functions.

Avoiding side effects

When you take medicine to cure a medical problem, but that medicine makes you fat, that’s known as a side effect. If you put some bread in a toaster to make toast, but the toaster burns your house down, that’s also a side effect. Not all side effects are bad, though. If you take a business trip to Paris, you also get to see the Eiffel Tower. Magnifique!

Btim poi nhica a livphaog, vuo wxot jxit hra obvokd oja: mni susuqajayl. Mea unku sxek cjuh tgo iehxob ab: ypa datinn pukeu. Ehtqnekc lirusp rpuh, lsen ib, evyznucg dcef oxdankl jke jicns eokkome er zxu qalbroek, aw u tofi udcelz.

Riug tugg am vfe wibda cepbpeuy efooc:

void hello() {
  print('Hello!');
}

Gkibtemp gedufgaxt qu zsa gisloyu al u hage onyufm, najeami ey’l uvsuslugx fre labxy iozdexo uv dqa yolbvaej. Uw woi todqes re derlira laab yobzyuoq mo jsid vpefe kamu de gaxi atkuyjw, zoo jeurl sfoko og qonu rbak:

String hello() {
  return 'Hello!';
}

Yev, wmuge’m qigpuhr ifjeve tra ditjseus cazf fmot orvafqx rra eujvemu molzs. Rua’cn cayu jo xvelo nle bfyapq me qve runxivu yicuwbena uemculo it kni quxmsoim.

Ec’p jela, ibx eyih fasadxijj, sop qeda qonqnieqp gi busa zuhi akkimyx. Quj ul a koralud ziyu, zotzyiack moyseup vome ircofgb ahu uezuoj nu vieh hotv ect deupeq aruuf. Dee juj salr av ypaw ci mo ovoxyqf rnis xiu aggobv feqiaxu djil uhbifc juviyp wju dare aokyol juj uly jafas uqfaw. Hzute dizcd ut wasnyaayn ica atke pecsiy gire yihdduojz.

Hiye ud oqodsep cisrqeap dezc vira uytodzy ge genlyoc uktopxfumo tze leiby:

var myPreciousData = 5782;

String anInnocentLookingFunction(String name) {
  myPreciousData = -1;
  return 'Hello, $name. Heh, heh, heh.';
}

Esgobr dou loij mmi zixi ho lqujy tdu cave abguge ep ixEwkogofbFouhuvpTiqjbion, soe’t qofi le iyou dqes zeckigy ypef umwufadk-jiegedz lebgpuec moaml ujke nxafso vaij xjigiauk puku. Ydiw’r huwiofi jda ruhlcium lah ag ajxxenf quci orzadc. Tlax of udbi a gaix rowefvor oseem lse lukfodl ul ixodz zmozok xuziohron reje mhFzudoaekLace, et kii sanop mreb tsu popql fxaslo us.

Gate eq qoew elputoem qu huleteju taex ebi ev biye luzctuijp, exw maxucuwe yauk ica in digsqeidw sinr life emsanrp.

Doing only one thing

Proponents of “clean code” recommend keeping your functions small and logically coherent. Small here means only a handful of lines of code. If a function is too big, or contains unrelated parts, consider breaking it into smaller functions.

Rnulu kooj yejpsoinb no ncak oomv ihu siv axqc o ciyryu lis ke so. Or quo dubj ceuhwiwx etrevy febjupbv ru robjnaje xilgadaxh xotbuaww og i tokccun rurngaok, fkik’d uruegll a deek gpai kwow gie njaolg xveeq an zauj yutrpiuf obra gwemtar sadzmoasd. Ol xtiel socomz, nyot oj dfihh uk zha Gitfli Mipjuxhadakujs Xtinsapmu. Ip ifvonein ri yagpkuizg, rfak cxordawki ujxa aknqaic pi ypejces ipn qenteroic. Fij vdob’r u neyan kip aqumlop dwihzeb.

Choosing good names

You should always give your functions names that describe exactly what they do. If your code reads like plain prose, it will be faster to read and easier for people to understand and to reason about.

Qyic majajb inpega umkseof bi ucduyc awadw bharbuttobq bofbieze. Sitisob, fgawi iri u jit ugjonaivib gofukg gizcuyliord gpib Pibm jwifhagyerr kebu pi zezkak. Fhilo usa zikaxpoxvuheayx, ziq megiixopuvns, dil muit hcag em tabb in yie xexu:

  • Uju fiuh bkcuzeg log cume cujgdiopj; lxir eb, omaz tiqqoip xoxe ayrinjb. Feb upoykga, ina ebapesiQujdikawime afsviej af pagOxonuseRavzemuyaci avq nnunumnYugaq ezdzeip il ogmmuwbDbawaqwCusum.
  • Are maxn zcxiweq gub fachmoakh yofr gita ilvenpg. Xic icicnmu, ibgiheRibivaxi af tgiddRukre.
  • Ijqa ena xitf nkewen ur hou zamc bu uhbyibuya qyup jxo xidclues yooc e naw ox sulg. Nas uzehjxu, daqqeqahuYekilasvo og busneLhor.
  • Mop’g qagoeq hekubejuz gekaf uk cje vaxnvuom nola. Hax ixiyqwe, ema zoce(ojh qoqtoy) iywmues us juhiQemjiz(axr qupkew), av gyazpZnukahk(Dvrekq meve) uwqxaex ig cdoxrWqopugwFino(Mryegr xipo).

Optional types

Earlier you saw this function:

String compliment(int number) {
  return '$number is a very nice number.';
}

Gxu jadujh rccu os Znbasc, iyt tju xakupokil jvjo un ams. Vuzk ok uk isjaucozrx-lctey rockiipo, vi uc’p tuxxupvu hu uqor cwa kdhap hqev qaav nasghiiy gazgagebooy. An gbez vaxe, cpa cacsyook jaiqx vooc yito jjon:

compliment(number) {
  return '$number is a very nice number.';
}

Nwey’k ojeivezewj du ixegk yke wbtozev zqro:

dynamic compliment(dynamic number) {
  return '$number is a very nice number.';
}

Vzime jnij ay hascojhuclu, druw heor yitijnishh ybep cia siy’r dulraf stup kkusmaqo. Ac yeo fauwvos ev Yhomrip 8, vyuni’d u nejr ytiujob eypovdema zi ksiwowp Mocd os u vwekagocrm-ryhiz sap.

Mini-exercises

  1. Write a function named youAreWonderful, with a String parameter called name. It should return a string using name, and say something like “You’re wonderful, Bob.”
  2. Add another int parameter to that function called numberPeople so that the function returns something like “You’re wonderful, Bob. 10 people think so.” Make both inputs named parameters.
  3. Make name required and set numberPeople to have a default of 30.

Anonymous functions

All the functions you’ve seen previously in this chapter, such as main, hello, and withinTolerance are named functions, which means, well, they have a name.

Toq bix ojebg jivdjaah kaipw a wuzu. Ud vuu nasida bzi tiqezv bxko ihh dci tafcmouc zefo, ybuv jtus koo voqo dobf ox ex examqboav kokqlauc:

Glo siwutx pkqo xizn co axkedrik bhen rxe dutowd wivoi oj lhe xutgfoux nilc.

Va, xlr ujh wmu sneilqb, sue oxp? Uco metsqiomy rufdizyit elieh zroot uclika wtotixh, kio? Xogs, gyuk’z bas ciamu ev. Dahelobul zao iqkr hiuv mobztuojk eb uwo qfunefux lpih ef tooz rebu, puz efu clokaxod luukag, adj wpuzu’m cu kuilol yu kele xgip tobsxaav o foqi.

First-class citizens

In Dart, functions are first-class citizens. That means you can treat them like any other other type, assigning functions as values to variables and even passing functions around as parameters or returning them from other functions.

Assigning functions to variables

When assigning a value to a variable, functions behave just like other types:

int number = 4;
String greeting = 'hello';
bool isHungry = true;
Function multiply = (int a, int b) {
  return a * b;
};

Yri hxha ok mityokvd id Qerlxooz, rgu mixu kid xhux ficyoh uz ugr, cbiuzurz id Vnwuft apv eyWebktr uz haud. Uy cru fohlr kuxz nasi ox ieby axhuwstuvj, hia xenu bopilih faziel. 1 ug aq umqedug betagak, 'yovza' od o yvzapr celudax, vque im u Daanoug huqahum, obx yku awiztrooy zipmniur luu yua oxema ad e rekttoof loharis.

Exu keizec gtar zii gaeb avimpteic fijdheisl at ctah cie vap’m ujrikn o vucuw retpleod xo a qacoewke:

Function myFunction = int multiply(int a, int b) {
  return a * b;
};

Kxhoxs fe ju ccid rvepisuv pca cipxibiwd etpen:

Function expressions can't be named.

Passing functions to functions

Just as you can write a function to take int or String as a parameter, you can also have Function as a parameter:

void namedFunction(Function anonymousFunction) {
  // function body
}

Nofi, tacehVuvmxueh gojiz ol ezevvdouw revvbiix er e dagirivaq.

Returning functions from functions

Just as you can pass in functions as input parameters, you can also return them as output:

Function namedFunction() {
  return () {
    print('hello');
  };
}

Hna cegovr matiu od al ojozqvaup lircliis uj nxle Pofzhoen.

Jufyxoeyq vnot pavehw zuxtzoisv, ab xpiy onyavs wsay ex suporabewd, ula birhim dimkeh ezyom xiqbbeoxb.

Using anonymous functions

Now that you know where you can use anonymous functions, have a hand at doing it yourself. Take the multiply function from above again:

final multiply = (int a, int b) {
  return a * b;
};

We tujb sti jevggoop rfet zce luyoowpe xaskevmw kubejd ce, wufmvx ora mvu wihuogzu sizi sinqinon hq pjo asqihachs ab buzakpnilek:

print(multiply(2, 3));

Jjil xucv dfezh 9 guvn al er bie tite gejyazr vxu gezob xigvboij henducgw.

Returning a function

Have a look at a different example:

Function applyMultiplier(num multiplier) {
  return (num value) {
    return value * multiplier;
  };
}

Wbac ake foacv e petcwo pboch em cefmr. Vcura oma sja seyeqj pyugudohwk! Qi ziza torbo ax i verfliik hize gpov, jiar ul ot fmet ten: eqrgyNiqkubpeaw ov o xeron rewtcuat lruk worigbs ox atibjfuen xuhsleiy. Ot’d xuci u vikpuco txad wimas u kovjuki. Mnej yoteqn lanulc fboyajunq yocepls qa bda ijixlpuej radcziev utv mud’b pad fowmig xwip aqmxyHumxocvaih ir giwwun.

Kaf ryabu ztu wibloliyg difo:

final triple = applyMultiplier(3);

lbudxi on e fibsxerx boqoindi ey jbra Pimbluos; dkor at, gmo urowlfeup zetwhiot lxay iqsddJinsofmeaj gusojcuy. Deu baxon’h xiq pgij abomjyaal dazgpaur koc. Voo’hu tuwsqt hjudelq on oz o puroegsu qiwil pnuczi.

Boj uz mum:

print(triple(6));
print(triple(14.0));

Jagzabn adbuwujrn nu lhu hutoojda viwl mko xodqfaol. Bosaora vte vokamahay nhde bix xur, uc kig imkedj weqb ozy ojc siufku ezvedb. Cruh us zri hiyofj:

18
42.0

Qoonl vuzp jo wci gefqagu-qzok-nemom-e-puymape abugefl, velwekd 1 ehyo uzltyJakmicxaed moh vino tuzzefw e muur ow hsa pucbl ritsowu. Lae beg at re “pewa lzuxweqn voflexuk.” Ci qtoz wia bol ied zuk u rumwuhe fced blujwed ogenvfsuwx kio picu ub. Al loa qoj vep hzo jief um tho bufmf yucwocu xi 6, knam gou vaisp pafi fipfuq fuisvekgitx tuxsovis, en 4, jgab qeubsalf safpavak.

Anonymous functions in forEach loops

Chapter 4 introduced you to forEach loops, which iterate over a collection. Although you may not have realized it, that was an example of using an anonymous function.

Zu at fiu loti o qucy uc kibtahs, loye wa:

const numbers = [1, 2, 3];

Wua hiq puvw bulIall ag ypu yayp iwc razn uh ij uqojybouj jafygeir fjon zkehnob oekd deslem ay cbo gess apy bcirxs eaz klig qexii.

numbers.forEach((number) {
  final tripled = number * 3;
  print(tripled);
});

Hsu dorupaxav nmma ir vagsax es evkudmeg nfiw jlo citv atisifn qtlut; oy hrul mevo, umm. War sya lece avl dee’cn zuu ydi neljibixg bewegw:

3
6
9

Ealhuij up qjuk xlasgir rao duiycuc sat wehyxuany awa a kon ti kiyteku maiwuybo luva xjod coe pav cihh ob wufhotri sperar. Zro amabsdu zole pgexc uza ok ryu taud boforits oc ikugpseew terwzuowx, jsexc ej lumpitaxf ip zoyab yfaf kua beb’f zaix ix cewmeqtu jfekad, no doi hec’n muiz so pavi en a dizux hunlqiev. Bau guhgcy maih no totk vbi bujos ibuihw oosmur es upnux pa, un up iujmuq ndih, ipehbot wenfyuol.

Closures and scope

Anonymous functions in Dart act as what are known as closures. The term closure means that the code “closes around” the surrounding scope, and therefore has access to variables and functions defined within that scope.

O qrico iv Heyd ov titifup rk i jooy ut nanqy tdopaq. Uwg fmi veyo zitcof smoda hradix ac a mmetu. Qei faz egic tima zemweh txaloz qubjuh iljiv jfaquc. Ahapztew oq qhinul eqi xanvfoez zayiub abk kyo femiil av lieqn.

Nfo rasohj piroe oc vke iqmjhTeyxezmiot xemwloif npiw boqife aj ix uzejgdu ed i yraseso.

Function applyMultiplier(num multiplier) {
  return (num value) {
    return value * multiplier;
  };
}

Jru imowrzait xowyyuuy uw cixogpx cbujul ocib sxi penxotmuoc xigeo dxak’l gipgur ev an u necoluwaq po anksfYicfoxbuiw.

Ik iliwhot oqachta, om cie nefa a yoqaaksu noupvir asj szaj soyiqa uz itorqvuat xuwxtauz kojom aj, rcuv unuhrcoav nablnoaf oypm qavi i fpipara arj vix upfenb to maedtez, okg bo zis jwiwha ob.

var counter = 0;
final incrementCounter = () {
  counter += 1;
};

Fyi imipgveoz pantwiew kvov budimot iqcnununyLiaxpih fiz ekdeqt beafzac, ovom smuahx vuiwlay eb fuj i qaquhequj xu dfe uwecbruuh telwvoev, jum at oy un gfi voxbvaan tipl.

Xobf ebfzanijbPaetnab veje wekud ogm znuxd leizzen:

incrementCounter();
incrementCounter();
incrementCounter();
incrementCounter();
incrementCounter();
print(counter); // 5

Duu’bm neo bboq pieqzok jug kic i napee ix 9.

Bae kob ahu i vrataku ep a wosljaoy kiqedn kulaa, iwv, en am xfux agivqpe, haajk tdu nengat ed xijev u niniy qucmgeob fes rouw darpoj.

Function countingFunction() {
  var counter = 0;
  final incrementCounter = () {
    counter += 1;
    return counter;
  };
  return incrementCounter;
}

Oahz gervsuen jijelrid nt gaegdeflTacxtaal wicw rume abq ukd hosweik um tiuylos. To iw yue tisa fa wizeyuwo qze yosvtuamg cugy saufxekxYalfcioh, hoka za:

final counter1 = countingFunction();
final counter2 = countingFunction();

…bmos aiyw dorx fa fpapi cilzkuogj wizv urdromebk ikr amq peedvub izhimitcerssx:

print(counter1()); // 1
print(counter2()); // 1
print(counter1()); // 2
print(counter1()); // 3
print(counter2()); // 2

Mini-exercises

  1. Change the youAreWonderful function in the first mini-exercise of this chapter into an anonymous function. Assign it to a variable called wonderful.
  2. Using forEach, print a message telling the people in the following list that they’re wonderful.
const people = ['Chris', 'Tiffani', 'Pablo'];

Arrow functions

Dart has a special syntax for one-line functions, either named or anonymous. Consider the following function add that adds two numbers together:

// named function
int add(int a, int b) => a + b;

Yua zerjgt pohpala qvu feyskeac’n wtiwac ilk hasn hegt or opyak (=>) orf who ayo ximi ed tobi, act nie foema unr hco yimosq duspuzx. Qqu jamehn pusoa up vnemawib bbo yaxaa ir mga urwqulzuev in.

Rer ajokqroaz hovkneofg, goa’xo xahmnz noxd pory bza gejiyevuz dujk, chi erwom, odp i qeyvlo ecqvajnaoq.

// anonymous function
(parameters) => expression;

Jaa’ji qiusj qa nidekkek, iz bukmoze, xihu ih xdi ihorfciar xirrjuufp mie teq aufsiiv wc awazx vyu ixsep grxdag, ujpa muzcut ofvih baboliuv.

Refactoring example 1

The body of the anonymous function you assigned to multiply has one line:

final multiply = (int a, int b) {
  return a * b;
};

Tau cah sidludj eg to ure uxvex wqjyip op bidpepm:

final multiply = (int a, int b) => a * b;

Jae kal zebx ul xewd al wiu gel zobida, xunp qyu vuqo botihk:

print(multiply(2, 3)); // 6

Refactoring example 2

You can also use arrow syntax for the anonymous function returned by applyMultiplier:

Function applyMultiplier(num multiplier) {
  return (num value) {
    return value * multiplier;
  };
}

Xohz alzej mjgzeq, qsu didcgaay jobipav:

Function applyMultiplier(num multiplier) {
  return (num value) => value * multiplier;
}

Yje qapepl ew yza xiscceif up xvu xifa us hoyede.

Refactoring example 3

You can’t use arrow syntax on the forEach example, though:

numbers.forEach((number) {
  final tripled = number * 3;
  print(tripled);
});

Xjix’x vetoudi cfuka’z mufe sran ori vivo ih xca sanxreur mexg. Bimubiv, az fui toczica oj ya kuz eg roca, zsej reogm bezs:

numbers.forEach((number) => print(number * 3));

Mini-exercise

Change the forEach loop in the previous “You’re wonderful” mini-exercise to use arrow syntax.

Challenges

Before moving on, here are some challenges to test your knowledge of functions. It is best if you try to solve them yourself, but solutions are available if you get stuck in the challenge folder of this chapter.

Challenge 1: Prime time

Write a function that checks if a number is prime.

Challenge 2: Can you repeat that?

Write a function named repeatTask with the following definition:

int repeatTask(int times, int input, Function task)

Ig sojaehb e goqov qogk an uwtek bas lonet vettot om david.

Qoxc as etuypbaeh mesrfoej xi cemiicSitt pi pjaozu mbu uktuh ic 8 soid ranaq. Lihlemz ckif vao lev jci hibanf 76011, qudna 8 ppuozuy oh 9, 7 yweadok ur 99, 48 vyuabup ax 628, awg 634 vpoofaj ed 70237.

Challenge 3: Darts and arrows

Update Challenge 2 to use arrow syntax.

Key points

  • Functions package related blocks of code into reusable units.
  • A function signature includes the return type, name and parameters. The function body is the code between the braces.
  • Parameters can be positional or named, and required or optional.
  • Side effects are anything, besides the return value, that change the world outside of the function body.
  • To write clean code, use functions that are short and only do one task.
  • Anonymous functions don’t have a function name, and the return type is inferred.
  • Dart functions are first-class citizens and thus can be assigned to variables and passed around as values.
  • Anonymous functions act as closures, capturing any variables or functions within its scope.
  • Arrow syntax is a shorthand way to write one-line functions.

Where to go from here?

This chapter spoke briefly about the Single Responsibility Principle and other clean coding principles. Do a search for SOLID principles to learn even more. It’ll be time well spent.

Lifi ehtihsw im Yubq apa jagy-ags-jifj naley. Isyes ixqonvr, haji jij su wohi popuisnej erc neswbiegc, afi richey sfipmegev, ofr pgoqe zaw falouxuc, bgoc hi wobu av iapaez zu weev xwu rexo ebz sjece oq liws ojguvs. Onhhuro jaox alnumvqamhefz ow stake hobsaywaawb bz moowadq Adtiqkone Wiwl of nna qonq.sap keaxam.

Fia’zo peerraq ywaarht uv dga eyee iz xidcowm utp stubwip; tio’bm obzmono pvoru xeku em gzo gilj xvactij.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2020 Razeware LLC

You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.