Reputation: 394
The task is about functional programming in Kotlin, a sealed list class is given and our task is to implement map, fold, replaceif, filter, and any recursively. So far i have implemented every single function except filter, but i am very close, i am just missing something.
Given List class:
sealed class List<T> {
class Node<T>(val head: T, val tail: List<T>) : List<T>() {
override fun toString() =
"${head.toString()} , ${tail.toString()}"
}
object Nil : List<Nothing>() {
override fun toString() = "NIL"
}
companion object {
operator
fun <T> invoke(vararg values: T): List<T> {
val empty = Nil as List<T>
val res = values.foldRight(empty, { v, l -> l.addFirst(v) })
return res
}
}
fun addFirst(head: T): List<T> = Node(head, this)
fun removeFirst(): List<T> = when (this) {
is Nil -> throw IllegalStateException()
is Node<T> -> this.tail
}
}
My implementation of map and replaceif:
fun <T, R> map(list: List<T>, f: (T) -> R): List<R> = when (list) {
is List.Nil -> List.Nil as List<R>
is List.Node -> List.Node(f(list.head), map(list.tail, f))
}
fun <T> replaceIf (list : List<T> , f : (T)-> T , p : (T)-> Boolean ):List<T> = when (list) {
is List.Nil -> List()
is List.Node -> List.Node(if(p(list.head)) f(list.head) else list.head, replaceIf(list.tail, f, p))
}
Lastly filter which is not entirely correct:
fun <T> filter(list: List<T>, p: (T) -> Boolean): List<T> = when (list) {
is List.Nil -> List()
is List.Node -> {
val it = if(p(list.head)) 'something' else 'something'
List.Node(it,filter(list.tail, p))
}
}
I basically want to recursively test if p is true for each element if it is, it should filter out that element else let it through to the new List. So i need to change my if/else 'something' so it works.
Upvotes: 1
Views: 813
Reputation: 4753
Okey, so, what would be the algorithm to filter a list?
So, implementation would be:
fun filter(predicate: (T) -> Boolean): FList<T> = when (this) {
is Nil -> this
is Node<T> -> if (predicate(head)) Node(head, tail.filter(predicate)) else tail.filter(predicate)
}
PS: I put those function in class
scope, so instead of passing a list into a function I use this
pointer. This allows to chaining calls, for example filter, map and foreach:
FList(0, 1, 2, 3, 4, 5, 6, 7, 8)
.filter { it % 3 == 0 }
.map { it * 2 }
.foreach { println(it) }
Upvotes: 1