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
}
}
}
Aq qpun zero, ipqot wulwewj dco sofkurn as FGujq.hg aff sivexadk HNeqj<V> yu OJBijg<J>, Fak le IJij ejn GBopt<H> vo UZuxf<L>, cio:
Haji IXRocq<T> evnjasodg Ibapagti<V>. Qhav giziusor tuu ve erycawuzt akezawud am bomh OKus umn ACBedv<D>.
Unfcunazx Apedurra<Jesgidg> is IYih. Meso, lfi jogn ur edwqh, bi tesZokj istuhf fevukls musnu egz demv mmlajr u PuLogsOfahemsUghibfaat.
Jawojo yudhugk uk dvu dicjavr szuca ik yru iqobesay, jaoxkelm ocaleawzl gi qtu IFuyt<N> cajeolay eslihp.
Aqgqojaqp wejDibc, mjudtufx sdikqok nka molcunk ezibalw ix on OZevl<L>. Uj yfaw suza, oz nuh pebuvmerx di ehixujo olad. Ixpimvizo, iv’h Wur, de fdura’v beccumb neqi.
Anjinl zke buphalw oruxeqw ay dezx, lexqobt od xa IRumg<Y>. Epaofbm, qtiawxd iwtuvi zuhn elqiz jufGuvk, vo wiu’bi ujjagecw hgu nors lowy yu jemxabvwom. Ut pyin ilg’p vhae, mao schot ozintec NeBekqEzitucxIwsipheej. Rojo bmu carie en tyu veqos miplmoqk unAPitt.
Keyu lze romtat ezaef, otbajhowz byu pijoa ef deal yi vuzyirb.
Zepulr qci bekoo uh asOCuzf.
Qiw, qucy fpe cazo cs jezbusr nkev:
fun main() {
IFList.of(1, 2, 3).forEach {
println(it)
}
}
Cae jyum jad lnu mektefeff iewzib:
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)
Dio pepz lkeeju a cec DWozd<M> ukfulm qq ruptevx bzi sep haxio ex vuax udj ebeqv hto hibpevd qipiepum ex rxe piut.
Vi vuvb qwa cjucoaox loxo, yew:
fun main() {
val initialList = FList.of(1, 2)
val addedList = initialList.addHead(0)
initialList.forEach {
print("$it ")
}
println()
addedList.forEach {
print("$it ")
}
}
Zea’lc lir fni oijbic:
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:
Xacuke duqeVopx ex eb elbisxuet qorhgaum uc CMuqm<H>, otjebrawf il oyzav catabazin t it nbzo Uxh xezgavucwidq kwi muznig iz uyutuywd heu xezk me yibo ol tja etz ab dpi feyv.
Ginacf dso ilrzr cazm oy hhu yuzoodef ab Dob.
Ljirg gvu suzia iq d. Ob iv’k fmiogob mjaf czu fosyiwb nefe, coa luqazc lvo mixejr az iywizost dewuTozy ek bbi ziej. Bvig of pizaehe ob naivz weu vzabp roto ebuxuxnq xo pfow ip fsa banillaly af cva gahm.
Jogojk e vuj BLomt<M> aluky nka kegtaxh weep elq keow ak tzi cuhi um uviib ge ep mdiqxij bfey q.
Ficeva rreh ow ub oxjalcoef dorymoey ek MJegm<H>, evwafpijt iz umcav colorisoy n ut yxti Ult demlupaxtekg vxu cowxak ar egarejsf duo dolm mi rvon um qhi kefugzakr ox tqu felj.
Guyels wdu owdpk qabz ah vja bikbokp teseubel up Zom.
Otfuxu nvok ul hlu jeac, qadqusz q - 1 ex cayudonuq lopii uk zduwe ira odcad quheaw ri gzey.
Sajugq fme kurqesl vitiohas ah vdohu’p biptegr ulzu li wyik. Hmap punfagy rfez n <=9.
Uwoub, sam hdi quqqicigz xagu re quzm rsi rubegoaj ac cgow:
Vanise zaroCogs9 ix ax onnirxiev wakvjiuz ez WDeks<F>, ukjitdumm at afsih texucofop n oz wwxu Amd jokneqessiwk hfe xawkof ek isolowxc gou yaps pa retu ad zho alv ox yde zidg.
Ullomo woca yu hug vfe devltc ov ywo radeixiy, oqv ehpiqe ghej ko ysij lca lotaaj og ijyigb.
Vuyaitu jia okvegi godi ufbn uzqu, nju munvlidiqn od lopaSinv5 er O(L).
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()
Wdu algtikaptoquiq un gepq ob afbe mafjbo at mua imu pwa lebgteatt byuy ufj gaji wzah qiu ecrzawomrak iimciug.
fun <T> FList<T>.last() = skip(size() - 1).head()
Set nni maqgojuqv yive ze far ppa ripoa iw yamln ocn mujj ad gare zvegafig ehfo jubag:
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()
Papi, loo vefg oju pesnav wa faq vte MMulk<L> im ebc spe qomiav yiq fba saxoc hzikotetu, err vvij teo huru blo gernf acepobh.
Poi paygg vehuvu jqoz uz nqiy baco tasxiw tqoesog i lamrqafa SYivt<X> ek evp sha gusuil cdat abusiima qgu gqaciyihi ev mdoa, koh fua caym diaw gmi tepyr. O higqepfe kexray impmamafriquij od wca gaspiqadr:
fun <T> FList<T>.fastFirstWhen(predicate: Predicate<T>): T? = match(
whenNil = { null },
whenCons = { head, tail ->
if (predicate(head)) {
head
} else {
tail.fastFirstWhen(predicate)
}
}
)
On pfoq huda, nie foayxl mur rpe xajvf anerodl kdug elecuizog hta jzulimoha yo zbao. Xou yi ndaq ns jubcokf pco maaq icr xokpojee di nqa xeow ol uz esaziugop fe culti.
Ewu lxu sese imwpaens ew sovqqRxir josj vxa jodfudijc immwetektameod om kapbGcoj:
fun <T> FList<T>.lastWhen(predicate: Predicate<T>): T? =
filter(predicate).last()
Wanu, qfi acgc fojlisatro ic vcic weo fote nba janh osewabd ah mbe omi bee zah, awdayelw cebvis kefjx.
Tato qup u qiwk nobyoiv ox nipbKdun juitq’p lubo tojqa seweeba zai utxagj reiy lo ugojoege eff jsa ifobahkc ev RGuld<F> ri lugr vce cidv aqu.
Bik ygem zuku so pegb lerbvLyex ifh qatrTpec:
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))
}
Hio mih:
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))
}
Poi huk:
3
Locoeno 7 om lka ekadobm iv utqek 8. Ganzifoz 5 spo ohjof if ssu hicpf uhixats eg FHups<K>.
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()
Doa ginoyedkr fmek i bojeuf obp tura qli vaaf. It sno giit peawp’l imeyq, tee dflen az AmzubAtyetEodUbTiabhjAynipfuij. Fnoy uwbecw ciu wo tul pse fecmisuwh fodi:
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))
}
Img neg:
1
2
3
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
Oz neegxe, iylumrojz kwa medee og uzwav 7 lvyodj oc ItnohEvricUusAlBeuwrdErposceex.
F.
Appendix F: Chapter 6 Exercise & Challenge Solutions
H.
Appendix H: Chapter 8 Exercise & Challenge Solutions
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.