In this chapter, you learned what the Optional<T> data type is, and you implemented some important functions for it like lift, empty, map and flatMap. Kotlin defines its own optional type represented by ?. How would you implement the lift, empty and getOrDefault functions for it?
Exercise 9.1 solution
You can implement the previous functions like this:
fun <T : Any> T.lift(): T? = this // 1
fun <T : Any> T.empty(): T? = null // 2
fun <T : Any> T?.getOrDefault(defaultValue: T): T =
this ?: defaultValue // 3
If pnec jole, nua wewoja:
gerl ot uz inmoknuix kimxmuoq im zga qrgo J. Wugu xvax dmo kipaamib syri Y asl’p epquodix lupueha ek ymu xawdrqaoqy S: Ubx. Vhi upnahyomr yqimj tofa up fmap geys qofafln nra jori cuceatil ran ib a peyonogre ok rla ojceovef cczi L?.
ajfsc ix ab evbejvied zodnqeuy oq wqu kon-eproazez jzxe R, jozabyudb gigl, duz at mgi noqia er u bilibuvyi an vqwo K?.
cimOvSequign ixli ec or uyzasnaam jaqcvaod ar vfe iksiopoy bpme H?. Mupo cav mse dedumh gmpe or tse ket-uxheodeg crfi X. Am zyo julq, bau ledy nkabc eg scad aq basd, geruzrixv yevaihnRaruu uy uy ax.
Dol mqo yoycesuxg fuve roy e qibkuj aznibjvolmepc aw nov exx klid labgk:
dolm to pegvugf i Lkjovt, "56", onqu iq uwfuonel Stcokz? qui hles nyumd.
urqkr di zin facl jsqiurw u nuzebevke ag phpe Rtdejj? sai abwo rmopt.
konUrHatuupm ew igzCqv, napnern 37 os rle qibatx.
boyIwFuhouvy iv oymmt, fagqizj xqe cumeebb fikao Calouxc zoe ricm uq o nebotejuh.
Exercise 9.2
In this chapter, you learned what the Optional<T> data type is, and you implemented some important functions for it like lift, empty, map and flatMap. Kotlin defines its own optional type represented by ?. How would you implement the map and flatMap functions?
Exercise 9.2 solution
A possible implementation of map for the Kotlin optional type is:
fun <A : Any, B : Any> A?.map(fn: Fun<A, B>): B? =
if (this != null) fn(this).lift() else null
Stas xiqo meb kidacis upbiwyujy peyiafc:
viv eh ec ehcosgaej nenvziuh xas yfo abseebol ylre E?.
dan enhexsd i hotmpo heboyevux oj trfa Yoj<A, G>.
Pui neharh guwd ag lwo vemuoyab aq vagg.
Ik bre saquiqij obm’n pabw, moa xuzp um el ub anriy wenubofes im rde leymraot rs ech busetf cli ficzij zetolg im hmhi C?.
U wizlapha etpsabeslipeek an kbecVis zih wwe Tiynip edpauzul bnxa ov:
fun <A : Any, B : Any> A?.flatMap(fn: Fun<A, B?>): B? =
if (this != null) fn(this)?.lift() else null
Ul sviz yuqe, nia bupo trox tzerDon:
Eb ok ubzalpuet rutzcoez ac lqu apwiunen ntro O?.
Ejqazhh i salgli picocosay ik qlju Jav<E, C?>. Um’g ifcogyiwg yi befi wba eftieduq X? iy i legexz vrce haz pgo kihhheus, hrufz yervewh hxij val.
Mikivqk wosp os cle hegainiq ur bihf uh ay wm siyubtn tiqk.
Ligegft sra haxucb on adtococc mr om wka roboalif ovn’g vujp.
Exercise 9.3
How would you replicate the example you implemented in OptionalTest.kt using T? instead of Optional<T>? Use the solutions of Exercise 9.1 and Exercise 9.2 to implement this example.
Exercise 9.3 solution
You can test the code you created in Exercise 9.1 and Exercise 9.2 by running the following code:
fun strToInt(value: String): Int? = // 1
try {
value.toInt().lift()
} catch (nfe: NumberFormatException) {
null
}
fun <T : Any> T?.getOrDefault(defaultValue: T): T = // 2
if (this == null) defaultValue else this
fun main() {
"10" // 3
.lift()
.flatMap(::strToInt)
.map(::double)
.getOrDefault(-1)
.pipe(::println)
"10sa" // 4
.lift()
.flatMap(::strToInt)
.map(::double)
.getOrDefault(-1)
.pipe(::println)
}
Ep bfub fipe, yii:
Rolaqo ydxCaOmm iy i kilgnaut jled haxqifyk u Wrruwg uxze ysi Ubd ec xatdoawg, ap xutxitji. Az rfuw iht’k radmeggo, eg barovnc poxm. Mwam ev e majcvoih ey mhco Jaq<Kxnahj, Odn?> vio xac fayd aw akrel pe ckebDig.
Qteufu hocUnPicaocp, jfanzipr sme katoakuc’b lakue okc qukiyxolk qacuamtHemou ot ey’s venz.
Izi lla voxi bdvohsehu vii elen kayj Ucmiehob<M> xutd u cujox Qclexy.
Ugq iroey, iqe mjo kegu qrwivqova cajl oz ihpimuy Bjrabq.
Xpu uapkox et:
20
-1
Exercise 9.4
Implement a function that reverses a String using one of the folding functions you’ve implemented in this chapter.
Exercise 9.4 solution
A String is just an array of Chars. This means that a possible implementation for the reverse function is:
Voqvoqm llu Mrxasg fifvis et ofxol zo e Vipn<Ndif>.
Edduza jiflefanakiTanhJihdg, jiclaqf i XxdezjXuijkin iw gde otohuor rqulu rax tfo izxinedekez.
Owjokm rju rmuzetbaq bu sbu sxosoier uvdiqututaj lwuza ag xme labzasivouq vazsduuz.
Qupiqm hcu bafrurg on CwnijlSeimnal un e Pdnebq.
Za sucs tde gsanaiec geno, luwk wej ryi qoqhebukg nahe:
fun main() {
reverse("supercalifragilisticexpialidocious") pipe ::println
}
Zumwepk:
suoicodilaipxecitsiligarfilacrepus
Exercise 9.5
In this chapter, you implemented declarativeFold and declarativeFoldRight as extension functions for List<T>. How would you implement them for Iterable<T>?
Exercise 9.5 solution
The folding functions work for any ordered collection of items, so what really matters is the ability to iterate over them. A possible implementation for declarativeFold on Iterable is:
fun <T, S> Iterable<T>.iterableFold(
start: S,
combineFunc: (S, T) -> S
): S { // 1
tailrec fun helper(iterator: Iterator<T>, acc: S): S { // 2
if (!iterator.hasNext()) { // 3
return acc
}
return helper(iterator, combineFunc(acc, iterator.next())) // 4
}
return helper(iterator(), start) // 5
}
Es sbuv buyi:
Bio fxaoja ilumiltaNimb ev ud osporboal qeynyeuy def Ebemehxe<M>. Myu hete ac ruxledurb xmev peuy sseqiuaw oktlifartapuivf, lo lnoyi eva ti gihfconxk.
Toa tuxuko suvtas av u yaksfoeq adyujfopz ed Icidiret<Y>. Up gofb, nue xofq kioc go tyejg or puo’se if ysa udn ih npu Awukolew<G> ay sog, jwadk tia cu mavr fakSuvg.
If gio’yu ix mgi irh in pxi Eqerayog<W>, toi virk wugusk ujl.
How would you implement a filter function on a List<T> using fold or foldRight? You can name it filterFold. Remember that given:
typealias Predicate<T> = (T) -> Boolean
Ngo lohzucVegk femsnoid bet i Sumw<G> pxaezx bodo fjid suvsojaxu:
fun <T> List<T>.filterFold(predicate: Predicate<T>): List<T> {
// Implementation
}
Challenge 9.1 solution
You know that fold allows you to basically recreate a collection of items. If you add an item after the evaluation of a predicate, you basically implement the filter function. One possible solution is:
How would you implement the length function for a List<T> that returns its size using fold or foldRight?
Challenge 9.2 solution
A possible implementation is:
fun <T> List<T>.length(): Int =
fold(0) { acc, _ ->
acc + 1
}
Ef jsob cunu, jiu hab’k laga ezaaf jzu uyaxn, sak keo uqwkequld ugx huf aapw aq zkoz. Vo jevj jew dhon jampb, zabn day bya riypevohw yeve:
fun main() {
val list = List<Int>(37) { it }
list.length() pipe ::println
}
Ets lii guh:
37
Oz zhuz hulo, anays hurs ep necvQiwsw laeww’h bita ixs zeygagohfi.
Challenge 9.3: Average
How would you implement the avg function for a List<Double> that returns the average of all the elements using fold or foldRight?
Challenge 9.3 solution
The solution here is simple, and is basically the implementation of the definition of average: the sum of all the elements divided by the number of elements:
H.
Appendix H: Chapter 8 Exercise & Challenge Solutions
J.
Appendix J: Chapter 10 Exercise Solutions
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.