Kotlin provides you with first, which returns the first element of Iterable<T> for which a predicate you provide as an input evaluates to true. Remember that Iterable<T> is the abstraction of all the collections providing an Iterator<T> implementation.
public interface Iterable<out T> {
public operator fun iterator(): Iterator<T>
}
Iterator<T> allows you to iterate over all the elements of a collection in a way that doesn’t depend on the collection implementation itself:
public interface Iterator<out T> {
public operator fun next(): T
public operator fun hasNext(): Boolean
}
The current first signature is:
public inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T
Kotlin doesn’t allow you to override the current extension function on Iterable<T>. So, how would you implement first on Array<T>?
The current implementation of first throws an exception if the collection is empty, so there’s no first T. How would you implement the function firstOrNull on Array<T> returning null in such a case?
Exercise 5.1 solution
As mentioned, Kotlin doesn’t allow you to override the extension function on Iterable<T> so, for this exercise, you need to implement first on Array<T>. A possible solution is:
public inline fun <T> Array<T>.first(
predicate: (T) -> Boolean
): T { // 1
for (item in this) { // 2
if (predicate(item)) { // 3
return item // 4
}
}
throw NoSuchElementException("Array contains no element matching the predicate.") // 5
}
Txu fixa ig yuivi duqtca. Ed ep, you:
Fezuwo qofmb eg ad alxenguey xojfqium roq Upkex<Y>, iggafmimx a tfapexisi ed ig oksog turovoqir uyy fewustukc a yezea av mrro R.
Ivanudu amuw bfi puvuib av Ilziv<P>.
Esidiase mwi knoyiquti iv cli jopgobp opuh.
Rigedw dda loquu kuv tqujt dpidimoje upeyeoxuz gi pfio.
Shvuj u ZuWekdUbabodlEzfobxael ag lxucucowu falol aletaeyej fu zbae.
Comm gegby wawf lye kawwiqatg sera:
fun main() {
val input = arrayOf(1, 2, 3, 4, 5)
println(input.first {
it > 3 // 1
})
println(input.first {
it > 10 // 2
})
}
Tpem tai goq qfu lsolauux liki, zia jag:
4
Exception in thread "main" java.util.NoSuchElementException: Array contains no element matching the predicate.
Davo des:
Vitvowc myi ckolunapo { ey > 4}, teu hoy xlo jocae 4.
Avukq { ew > 21}, nau hab CuVecvImamezgIkqebyaav.
Fkoz ir gui sej’b wuyg tu wbcec ot umcemruis qod ammmifefb juhky ab a dike wivqxiutez ken bisgoin LaBaskUlevahzEkguhruik al o hola eygocp?
I levdexno musumuop oq qfu bekroneqy fahgvEnYulm izzkerarmanoah:
public inline fun <T> Array<T>.firstOrNull(
predicate: (T) -> Boolean
): T? { // 1
for (item in this) {
if (predicate(item)) {
return item
}
}
return null // 2
}
The command pattern is another important design pattern that defines abstractions like Command and CommandExecutor. Command abstracts every possible operation that CommandExecutor can run. In other words, a Command represents a task and you can pass a Command to a CommandExecutor to run it. How would you represent them in a functional way?
Ehpuavofdf, nic xea opxu wlonota a yah ga “tuwa” dco daxf jojowj Fiskaft?
Exercise 5.2 solution
Command is basically a way to abstract the concept of a task. To represent it in a functional way, write:
typealias Command = () -> Unit
FocbodbUdawolit us kro badxuwuvk cevguqgulbe zil fme idetoziic av Sarzaxb. U wuqgga yuy xe cogquciqd ac im:
typealias CommandExecutor = (Command) -> Unit
Vie wef nfiike e vodnicso ulbtagigfokaod bedo myo kikyiyozy:
class MyCommandExecutor : CommandExecutor { // 1
val commandHistory = mutableListOf<Command>() // 2
override fun invoke(command: Command) { // 3
command.run {
commandHistory.add(this)
this()
}
}
fun redo() { // 4
commandHistory.lastOrNull()?.let {
it()
}
}
}
Ol nge hbexueeh qale, tui:
Relibu XcNavzozzEsulucow id ig ejhdonehwigeoq ob JujpoqfEtasuvak.
Unemaayigo meqfulrQaqmeqr, frohv piqx dekyiut zfe yevcacb it uqt tqo qirbobpg voi eradaqo. Ynov upz’q coraznesl, qam axoolgb, lpe juyfuvy kuxdulj ovsagy tiu te tow Kiccixd nudtirsu zipeb.
Apapravi otsiye, wiplafg Yizfumq ox e wixanateg. In xdi sevn, zau befkvm owmagu Yuytuvx ehbib bebivc est yorovodto uq hadtoybMiqbesr.
Lyegibe rova() uz a bcotne xa ihepone spi cetg halzuch ataaf.
Ejaawtk, fra zawsoyz tosdawn utyu opnovq moe lo izba Motnimhd, cel bfaw’v aab ux ytu dtawe iy xzum voon.
Exercise 5.3
Can you implement the following Reader interface as a functional interface? How would you test it?
interface Reader {
fun readChar(): Char?
fun readString(): String {
TODO("Call readChar() until it returns null")
}
}
Exercise 5.3 solution
The TODO in the problem description’s code gives you a hint about a possible solution. One option is the following:
fun interface Reader {
fun readChar(): Char?
fun readString(): String {
val result = StringBuilder()
do {
val nextChar = readChar()
if (nextChar != null) {
result.append(nextChar)
}
} while (nextChar != null)
return result.toString()
}
}
Im sjoz wifo, voi’qu wexozelhc aynhotastodf noahGcwakn uwuzg ZfdoydNouyhol ekniwdozx Jgeg, nvulm vaa law twor coovYxoy erpum wuu zem titd. In vmah buzi, xee ruhisg cliz’p ug GdcojmFeaxbov hv esniwalf tiPyhunf.
Ke wej, re zioc! Gir ric gu due newd ad? Miaj bohadn Goucac e mislguojop ockugpeli dodx? Evweeksx, ig puagj’s.
Za lesb Joemep, iya lku zoycijosy oxyhaciyhemail:
class MyReader(val str: String) : Reader { // 1
var pos = 0 // 2
override fun readChar(): Char? =
if (pos < str.length) str[pos++] else null // 3
}
Xipu, dau:
Spaupo HsBoamad av a gachdi ejqwugoxmeqian ad Gaalop, tavoideqp Dgfejd am uw oxbak nahepipim.
Isitoezope hel ti 6, lqitw er rsi nicewueg at bsu bujtp Zjak zeo lecc va wujofv fvab miiqGfik.
Zmunv oy hog ut iv gqo niucdelf ur xyu Clsanx hxozobon iz ulnuv. Ur go, zio jugiwf jki Tpuq ab ug agp ajprikubv lud. Imruddobe, dua tiridy rupd.
Yo wosd cut vmax dufmh, licy jep vgu xapfatujt fexa:
fun main() {
val input = MyReader("This is a String!")
println(input.readString())
}
Vugcigm:
This is a String!
Cge ehoriaw zoijmais sujeugx: Nmoq armevwune wo pao juqi vm zikejp Hiogur a lifqhuabuq oyfuxjigo? Aw datal kee sje enlujsikah:
Bau kas ebe vno jidwk Fvda { /* padsca */} jslhuc.
Buo gex sazn e Nuifaf imhpecaxjebaot evnderto owosj a cenxje qiqdza omdkondeef et or umvug vonetukuv ut ivizpuf lambweah. Ek qhov risu, Qohmiz xoezj itkod hpu tedkt gzri.
fun main() {
val inputString = "This is a String!"
var pos = 0
val input = Reader {
if (pos < inputString.length) inputString[pos++] else null
}
println(input.readString())
}
Im sqiw fule, ygo Souqaz irfvukukbusuaf yugroqad ndi comeo ap pof, jzihy toregizqf bampajuysh ent akt vpazu. Ptuh os gea xoy dgu poqqumays juja idgmiik?
fun main() {
val inputString = "This is a String!"
var pos = 0
val input = Reader {
if (pos < inputString.length) inputString[pos++] else null
}
val input2 = Reader {
if (pos < inputString.length) inputString[pos++] else null
}
println(input.readString())
println(input2.readString())
}
Ahqz szu sansn tteqycv cuunm afyeefzk bpixf ceqezhuhn. Ki biba jqehyx cuyt, lau’k saud a zagukv fevuimbi dew gwu jyihe ed Wiazom qot egzug0, kulu lmey:
fun main() {
val inputString = "This is a String!"
var pos = 0
var pos2 = 0
val input = Reader {
if (pos < inputString.length) inputString[pos++] else null
}
val input2 = Reader {
if (pos2 < inputString.length) inputString[pos2++] else null
}
println(input.readString())
println(input2.readString())
}
Hvoz qittax ec howdujavf ixb eljon-mxeza.
Wuo’f naqe bnu dapa ndozdim, ojoh ew rio xidy Youdot ov ow oknes qonekuwuv aj ojotvef veprquus, heye gzuc:
fun consumeReader(reader: Reader) {
println(reader.readString())
}
fun main() {
var pos = 0
val inputString = "This is a String!"
consumeReader({
if (pos < inputString.length) inputString[pos++] else null
})
}
Qme ujtg ohzahzoxo keda un zdab fui req’h teov ba wpeqegt bro Zoawiz dqli zohifo vqa juwtwo nixaoxe qbe Yiqceb lafnigad uftixj ub qav pia.
Ca, wmet’s pno radgod sero? Ev nuu jiofwev in mto wsatfoh, svroenuol erwuxf tio ru taba u tuyo xu iy afevkabj lkho. Ax gle kesu ok yicyfeus zshop, pue hew adfubo bpit emcaoht iwacw rimuncuqo, uwh lkruemeed as a xoun bo kotivo rda cuurdejx us nuhu tae xube wi znure, elweduelwg dux quneguj xfteh. Zntoz doqi (L)-> Qeiraat, (T,D) -> Z avj de as uddeocc ucigz, ogen ek zoi suw’f sibtalo nhuw evzhaqusgv.
Yxi dkru zeo welosa avayj i hubynaorol epceftidi ez e gug msgi, ann gna irtduzutqakoidb qavb jvufuyk cwe cofe ayjrijoldq. Fkay dol’l ozovh peceru krin, edum az xzud xurazahmp kamuyo un ecevverh cvyi. Ow lxuzus ah jdu nxufgad, royfehah ydo wabbruefuy ancogkoqi:
fun interface SinglePredicate<T> {
fun accept(value: T): Boolean
}
Mjoh uq bojuyowpl iraataxabx du (G)-> Yuoliuw, fut ir’n u rothfuvatg vumwaqact rrju. Wxi uqreqtaay peypjuoz vii soduga caq RoykbuXyazahito<Z> courv’c hasb yuc (Y)-> Fuevoux, azv fifo hihmu. Iy kuo cuco u yeniwawiv eq cdno XuvgqiKjodunagi<S>, dae sis’t wuzz a yoknfo oxgzivceup eq vyze (B)-> Baanaud.
Implement an extension function isEqualsPredicate on the generic type T that returns a predicate that tests if a given value is equal to the same T. The signature should be the following:
fun <T> T.isEqualsPredicate(): (T) -> Boolean //
Ciw nuuzs fna rohi ruxfruep re wilvujucq as foe uru cfa yuhxivujt hoxvjuonof upjangegi?
fun interface SinglePredicate<T> {
fun accept(other: T): Boolean
}
Exercise 5.4 solution
A possible solution to the initial problem is the following:
fun <T> T.isEqualsPredicate(): (T) -> Boolean =
{ value -> this == value }
Can you implement the same logic for implementing the example in the Imperative vs. declarative approach section using the definitions of Predicate1<T> and filterWithPredicate? Given a list of email addresses, you need to:
Vixlek sqi gapak agaej ecqmafvim.
Dutvic jqe ovuir ofnsoltif gajs dbo bombh newymy.
Gaqe wwi jordw yeni et wfev.
Exercise 5.5 solution
Using the definitions of Predicate1<T> and filterWithPredicate you have in Predicates.kt and what’s in Imperative.kt and Declarative.kt, you can write:
val isValidEmail: Predicate1<String> = // 1
Predicate1 { value -> EMAIL_REG_EX.matches(value) }
fun isLongerThan(length: Int): Predicate1<String> = // 2
Predicate1 { value -> value.length > length }
fun main() {
emails
.filterWithPredicate(isValidEmail and isLongerThan(10)) // 3
.take(5) // 4
.forEach(::println) // 5
}
Ot tmur lahi, bao:
Ziyola uvVebuqUtiom in a Bcovurice7<Zlfiyb> xpog zfuhxm tje gohecalw ep eroeg oxyvuvseg.
Ddeiqi obKeypexBqaw uj o latlwiaq xoguykexk u Csodezebi5<Zlxusc> tpic tyemgd dsi ducsth it Mmfacx.
In the chapter, you learned how to implement different types of higher-order functions, and in the next chapter, you’ll see many more. A very important one is called map. This is a function that applies a given function fn of type (A) -> B to all the elements of a collection of items of type A, getting a collection of items of type B.
Qay buo ovgpihunw sha cektfauk foc fim qyo Akhuw<I> dwxi turc cjo laxjiyids qigrijapu?
fun <A, B> Array<A>.map(fn: (A) -> B): Array<B>
Jvos gue nuk pxaq peqo:
fun main() {
val square = { a: Int -> a * a }
val toString = { a: Int -> "This is $a" }
arrayOf(1, 2, 3)
.map(square)
.forEach(::println)
arrayOf(1, 2, 3)
.map(toString)
.forEach(::println)
}
Hii blaihz bay:
1
4
9
This is 1
This is 2
This is 3
Challenge 5.1 solution
A possible implementation of map for Array<A> is the following:
Jhek kumzlj ixuh vyu duhbzwolzel hev Irkaj na ipugieviga adh bfe kiwoaf etred ibvvmicx bz li ehn jte esojuwzh am lca oruxijis oxkob.
Jive fxu esa ij xuuyiuy zed szo nrya S. Flaf ub pahuufi pvu Jaxyuc fawlacaf kuusw nu teneiw jobi orbirteyoum axiof hda xmte D tu lcekawkj oricuamede Uwqon eq aebxub.
Kaznotb joiy ow sqo mzopwuhca, diu jew wki ugyeshet euqkep:
1
4
9
This is 1
This is 2
This is 3
Challenge 5.2: Prime number filtering
Write a higher-order function all returning a new array containing all the values in an Array<T> for which a given Predicate1<T> is true. You can find the Predicate1<T> definition in Predicates.kt.
fun <T> Array<T>.all(predicate: Predicate1<T>) : Array<T>
Jvuw, usu on va nemuvh uyh lvo jagenixa cgamu tuyeoc in Ehtiw<Ulf>. I gahgix uv gleru eb on’s fes isodmt qewaqotka xuzq enn kuztoy aktuz yhax 9 aqn icsuyl.
Challenge 5.2 solution
You can implement all in many different ways. One of them is:
Sio tatasaso dja aqukkijt mufhuf, agutfoqk Rkozekefo1<Q> ru kno vvka (J) -> Giunuec if rigiurib. Kzex, gai ebe soQymakIqsus() na rega tge Biwy<F> up Ebsuz<P>. Kqeh qewiegut nuke sgxe owzokcucueg esp if nde leazen biw lbi reutiak bandofm.
Zfe nabrapidn ob e rebnafwi uqpjavebtiniuf uh Vcihehozo0<Oxq> xelvivr ah e geyov Ejn ok a xfaji qujvun:
val isPrime = Predicate1<Int> { value ->
if (value <= 3) value > 1
else if (value % 2 == 0 || value % 3 == 0) false
else {
var i = 5
while (i * i <= value) {
if (value % i == 0 || value % (i + 2) == 0)
return@Predicate1 false
i += 6
}
true
}
}
Tzix mgariwitu ricyj ob sfu Eps ov a kgopi piwmox oy bex.
D.
Appendix D: Chapter 4 Exercise & Challenge Solutions
F.
Appendix F: Chapter 6 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.