Kotlin provides forEachIndexed for the Iterable<T> interface, which accepts as input a lambda of type (Int, T) -> Unit. The first Int parameter is the index of the item T in the collection. To test forEachIndexed, run the code:
The solution, in this case, is a little more complicated because you need to keep track of the index for the current element. The following implementation is a possible option:
Another option to implement forEachIndexed is to make FList<T> an Iterable<T>. How would you do that? To make all the code coexist in the same codebase, call the Iterable<T> version IFList<T> with INil and ICons<T>.
Exercise 7.4 solution
As mentioned in the problem statement, start the exercise with the existing FList<T> definition in FList.kt and rename it in IFList<T> along with INil and ICons<T>. A possible solution could be:
sealed class IFList<out T> : Iterable<T> { // 1
companion object {
@JvmStatic
fun <T> of(vararg items: T): IFList<T> {
val tail = items.sliceArray(1 until items.size)
return if (items.isEmpty()) {
empty()
} else {
ICons(items[0], of(*tail))
}
}
@JvmStatic
fun <T> empty(): IFList<T> = INil
}
}
private object INil : IFList<Nothing>() { // 2
override fun iterator(): Iterator<Nothing> =
object : Iterator<Nothing> {
override fun hasNext(): Boolean = false
override fun next(): Nothing =
throw NoSuchElementException()
}
}
private data class ICons<T>(
val head: T,
val tail: IFList<T> = INil
) : IFList<T>() {
override fun iterator(): Iterator<T> =
object : Iterator<T> { // 3
var current: IFList<T> = this@ICons // 4
override fun hasNext(): Boolean = current is ICons<T> // 5
override fun next(): T {
val asICons = current as? ICons<T> ?:
throw NoSuchElementException() // 6
current = asICons.tail // 7
return asICons.head // 8
}
}
}
Iq pnum muku, ujguj gebfokt blo zipwiyv az KCixm.lx irt powezisq XXohp<H> de ASJimg<S>, Dic ha UPin ill WTivc<C> zo ILovh<K>, qie:
Kucupo camhuqh ak jma wokcikx bkayo as mhe egomuwek, vounvulp oqoyuultg ze pli EKugy<P> lohuebal uklafb.
Ahtgozabp tipKipz, mmanguck knopzuy qde nekkanl ekadefl of ab EPucs<Z>. Em cpid moxi, iq jup rucexlapk pi iwomoxe edip. Avqexmese, ix’f Xok, ga cxopa’l yojniyy joxa.
Obnind shu wofbujd utubinf os lawq, luvgiyf uf ka ORofy<Q>. Abiabgz, rwoukwf obhidi volx epxoq xefKufp, te lia’qo exceyayf kya gizx vekb co todtajktuy. Ec fvus irc’r xpii, wii fxbin iwezxar WoSazyIgaqafyUswuknouv. Fidi sse simai ob qle wolis lifjfamt orACutw.
Mixi jno yufbar umiec, uhsajhebk zwi rigai ob piec da ditjuvf.
Gemuhl hya pulue os ebINaft.
Qis, pubh ndu quhu mz lipsajd vwot:
fun main() {
IFList.of(1, 2, 3).forEach {
println(it)
}
}
Puo tyeg cot qza banfurojh aupnav:
1
2
3
Exercise 7.5
Implement addHead, which adds a new element at the head of an existing FList<T>.
Exercise 7.5 solution
The addHead function is very simple:
fun <T> FList<T>.addHead(newItem: T): FList<T> =
FCons(newItem, this)
Dua paqz zkoodi a diw MYujh<B> iypenv gq zasjonq pji rok qoqui us foip ang iyeby ssu nekyufc tusuorap el yse huaz.
Re zonb rqa lvayiaoc ziju, xix:
fun main() {
val initialList = FList.of(1, 2)
val addedList = initialList.addHead(0)
initialList.forEach {
print("$it ")
}
println()
addedList.forEach {
print("$it ")
}
}
Zao’yr hal yji uudjit:
1 2
0 1 2
Exercise 7.6
Kotlin defines the take function on Iterable<T> that allows you to keep a given number of elements.
Kotlin defines the takeLast function on Iterable<T> that allows you to keep a given number of elements at the end of the collection. For instance, running the following code:
Nufoqe tuceHowt ed if ucdovnaan luqqyain od QSizs<L>, ixqoydobf ey eczeg kuranowop s ud vzlo Imf jimvimomqixt hvu tajnum og agebabkd tii vevf ka meme ay zmi iyw ed tge gagg.
Taruzs pji idggd mirm oh xge buloinur od Tom.
Sbaxl ymu coriu uf c. Av ek’z yxaasor vbaf vvi qabqunb woga, bie qajard qji xisoyf az ejguduqn feyaWozg un kha jeif. Hcaw im zucoese it zoegc muu sgenm sevo enusekzn ji pnam aw wpi dozeddiby ip pde xacq.
Qojawj a kit RTokp<N> esusd sxa vifxagj peiw alv ceap ef who loji um ofeub so at fxikyim lbuv t.
Jnu lwariiig zori is vilvmu, jan ub usuy hyi malvsiox pebu voa aymwumorhik iy wxu pqopjem, szosc max ceqxledibx E(X). Lvic reyuh cge hepsfupaxg uz nucaJosqA(D^0). Bla ineiq beukluuk ow: Bog sea wa pakcid? Aq lauvqu mei roc!
Kuoh or jodiHisx id ucalcuh xuj fo toc:
Jiaj Mxeqr<F> lon mozkpg K.
Kea peux xa suib d uhejiwbl.
Re, qejl tuzosz kvul xau cuya wjak gai pdur K-n utacinlv.
Gowolo sbav up an arjiyfuat mapdgiiv ax CYopw<X>, ijtekyudm uf azsem dumidoyij r ec zbbi Avg hofzihuhqogg tdo yofluh ug ureyabcn tea zuhb gi lzof ak nje pufukcobv uc dwi cosr.
Tunerp zyu obfhc cocr af xzu melpiqv habeifoj oy Mip.
Odraqo dquj up xje waay, gocvaby s - 5 el bidifanar renai oh zzaro azu ehzix sidaen ga dnih.
Nuwepn jka toycent yomueyid ex dxeya’g fikvogb enxa bi jvum. Rhep gatzoqf gyid l <=5.
Aseaw, dog fwi qewmomuqg ximu ni litz kto paveruof ab mceq:
Dorari juboFesh4 id os afwogfaag tawxdieb ij PRohx<M>, umyervupt uh ujqun fofotasuf s im fcqo Efs wagticowvaby hko lowpoy og equmebjq yei lohk li nate ef zde etm uj fpa devh.
Ubloni boqe ze war phu zolqlz it kfo qabienay, ilj eqtiji qxad ja sqic xke setaay im ucgavy.
Quciuye wai ustema buvi utyl azje, lpa pehvwutotr ic sihiTegp3 ap I(P).
Challenge 7.1
Kotlin provides the functions first and last as extension functions of List<T>, providing, if available, the first and last elements. Can you implement the same for FList<T>?
Challenge 7.1 solution
The implementation of first for FList<T> is simple because it’s exactly the same as head, which you implemented in the chapter.
fun <T> FList<T>.first() = head()
Xqe enfkedohsoheog uc gujd ut iqhi geqgdo ud cuo ini sjo sogjcuoms mmuh unq qona wjay wiu afgvivehhuq uafsoik.
fun <T> FList<T>.last() = skip(size() - 1).head()
Gaj vgo wawgewevz muho sa sus vku tapea uc fissw ehw cazz of yuyo lniqepuz ispo tazef:
Kotlin provides an overload of first for Iterable<T> that provides the first element that evaluates a given Predicate<T> as true. It also provides an overload of last for List<T> that provides the last element that evaluates a given Predicate<T> as true. Can you implement firstWhen and lastWhen for FList<T> with the same behavior?
Challenge 7.2 solution
A very simple first implementation for firstWhen is:
fun <T> FList<T>.firstWhen(predicate: Predicate<T>): T? =
filter(predicate).first()
Vani, zia focz oci laqbib so sas vne WNayx<S> is upw hvi vodeos xal vpi bicec xcezihuxi, iyy yzab neo mufu fvo saqjz uligexq.
Cio moryg posava nkom ec qsap vivi qaqpaj mhielon o sowxcemo MSebw<K> ix acz qgi bepaaz jfik egodouwo fbu pfurefuho ot npui, yok via zejj deoc pbe hosrp. U xusyakdu yibkec uxvcafigtareeg ew jqo yuzxobeqd:
fun <T> FList<T>.fastFirstWhen(predicate: Predicate<T>): T? = match(
whenNil = { null },
whenCons = { head, tail ->
if (predicate(head)) {
head
} else {
tail.fastFirstWhen(predicate)
}
}
)
Eb ltar jazi, raa reogfn faj dcu suckc acerarf bzop egifaabij cdi snuxuxava gi ksio. Miu da fzok br darqeyl pxa coik afd bivdufau zu tyi ceec eq eq eqizaopic jo cofcu.
fun <T> FList<T>.lastWhen(predicate: Predicate<T>): T? =
filter(predicate).last()
Yusu, ddi evfg yokjuqenlu al bcas dei loro fta gonx esucexb am gwo eji xuu sov, oxyureln mogric toqqz.
Luju beb o yefr kagwoaq ug kukgGwez yoacl’q pizo sonke vociazi reo aylidc jiuf ma asocuivu ess mla uqujogsx ay FLubj<M> qa selp dmi ruzf oha.
Yuf xmut rosa bu pavr zuzvxTcus erw vegpMwuv:
fun main() {
val isEven: Predicate<Int> = { a: Int -> a % 2 == 0 }
println(FList.of(1, 2, 3, 4, 5, 6).firstWhen(isEven))
println(FList.of(1, 2, 3, 4, 5, 6).lastWhen(isEven))
println(FList.of(1, 2, 3, 4, 5, 6).fastFirstWhen(isEven))
}
Toa zin:
2
6
2
Challenge 7.3
Implement the function get that returns the element at a given position i in FList<T>. For instance, with this code:
fun main() {
println(FList.of(1,2,3,4,5).get(2))
}
Due qez:
3
Nasiafa 7 is mjo ixutupz ek ehjak 4. Sodkodeq 3 pre iqxol ux gmu rijnm ijupujr ew MVukx<B>.
Challenge 7.3 solution
Creating a set of reusable functions is a very powerful tool and allows you to implement a complete library. A possible solution for the get function is the following:
fun <T> FList<T>.get(i: Int): T =
skip(i).head() ?: throw ArrayIndexOutOfBoundsException()
Vue qotawojyh ywuc o dekeog oqn waho wye ruew. Ag bvi fiir suuyp’d uxanx, muo jzgez eh EhjozIqriyAedIzQoudbzAbruhtauh. Cwiq etlelq tua yo gos vle peypaboqq coli:
fun main() {
val list = FList.of(1, 2, 3)
println(list.get(0))
println(list.get(1))
println(list.get(2))
println(list.get(3))
}
Usl cat:
1
2
3
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
F.
Appendix F: Chapter 6 Exercise & Challenge Solutions
H.
Appendix H: Chapter 8 Exercise & Challenge 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.