Unique to functional languages? I investigated & created how to use the list operation function of Kotlin.
range.clj
(def list1 (range 1 6))
(def list2 [6 6 7 8 7 7])
range.kt
val list1 = IntRange(1, 5)
val list2 = listOf(6, 6, 7, 8, 7, 7)
Kotlin is a Closed Range, isn't it?
concat.clj
(conj list2 10)
(concat list1 list2)
concat.kt
list2 + 10
list1 + list2
repeat.clj
(->> (repeat 123) (take 3))
(->> (iterate #(* 4 %) 3) (take 3))
repeat.kt
generateSequence { 123 }.take(3)
generateSequence(3) { it * 4 }.take(3)
filter, remove
filter.clj
(filter even? list1)
(remove even? list1)
filter.kt
list1.filter { it % 2 == 0 }
list1.filterNot { it % 2 == 0 }
some
some.clj
(some #(when (even? %) %) list1)
some.kt
list1.find { it % 2 == 0 }
list1.first { it % 2 == 0 }
If none match the condition, find returns null and first raises an exception.
map.clj
(map #(* % 2) list1)
(keep #(when (> % 3) (* % 2)) list1)
(map-indexed #(* %1 %2) list1)
(keep-indexed #(when (> % 3) (* % %2)) list1)
(mapcat #(list % (* % %)) list1)
map.kt
list1.map { it * 2 }
list1.mapNotNull { if (it > 3) it * 2 else null }
list1.mapIndexed { i, v -> i * v }
list1.mapIndexedNotNull { i, v -> if (i > 3) i * v else null }
list1.flatMap { listOf(it, it * it) }
reduce.clj
(reduce #(* %1 %2) input)
(reduce #(* %1 %2) 10 input)
(reduce #(if (> % 20) (reduced %) (* % %2)) input)
reduce.kt
list1.reduce { acc, v -> acc * v }
list1.fold(10) { acc, v -> acc * v },
list1.reduce { acc, v -> if (acc > 20) return@reduce acc else acc * v }
If you want to stop reduce in the middle, you can use labeled return.
The number of things that must be made will gradually increase.
distinct.clj
(distinct list2)
(dedupe list2)
distinct.kt
fun <T> Iterable<T>.dedupe(): List<T> {
if (count() == 0) return toList()
return fold(listOf(first())) { acc, v -> if (v != acc.last()) acc + v else acc }
}
list2.distinct()
list2.dedupe()
shuffle.clj
(shuffle list2)
shuffle.kt
import java.util.Collections
fun <T> Iterable<T>.shuffle(): List<T> = toMutableList().apply { Collections.shuffle(this) }
list2.shuffle()
apply is convenient, isn't it?
groupby.clj
(group-by #(mod % 2) list2)
(frequencies list2)
groupby.kt
fun <T> Iterable<T>.frequencies(): Map<T, Int> = groupingBy { it }.eachCount()
list2.groupBy { it % 2 }
list2.frequencies()
interleave.clj
(interleave list1 list2)
(interpose 999 list1)
interleave.kt
fun <T> Iterable<T>.interleave(list: Iterable<T>): List<T> = zip(list).flatMap { it.toList() }
fun <T> Iterable<T>.interpose(sep: T): List<T> =
zip(Collections.nCopies(count(), sep)).flatMap { it.toList() }.dropLast(1)
list1.interleave(list2)
list1.interpose(999)
reductions.clj
(reductions * list1)
(reductions * 10 list1)
reductions.kt
fun <T> Iterable<T>.reductions(function: (T, T) -> T): List<T> {
if (count() <= 1) return toList()
return drop(1).reductions(first(), function)
}
fun <T, R> Iterable<T>.reductions(init: R, function: (R, T) -> R): List<R> {
if (count() == 0) return listOf(init)
return fold(listOf(init)) { acc, v -> acc + function(acc.last(), v) }
}
list1.reductions { i, j -> i * j }
list1.reductions(10, Int::times)
partition.clj
(partition 3 list1)
(partition-all 3 list1)
(partition 4 2 list1)
(partition-all 4 2 list1)
(partition 4 2 [:a :b] list1)
partition.kt
fun <T> Iterable<T>.partition(n: Int, step: Int = n, pad: List<T> = listOf<T>()): List<List<T>> {
var tmp = toList()
return mutableListOf<List<T>>().apply {
while (tmp.count() >= n) {
add(tmp.take(n))
tmp = tmp.drop(step)
}
if (!pad.isEmpty() && !tmp.isEmpty())
add((tmp + pad).take(n))
}
}
fun <T> Iterable<T>.partitionAll(n: Int, step: Int = n): List<List<T>> {
var tmp = toList()
return mutableListOf<List<T>>().apply {
while (!tmp.isEmpty()) {
add(tmp.take(n))
tmp = tmp.drop(step)
}
}
}
list1.partition(3)
list1.partitionAll(3)
list1.partition(4,2)
list1.partitionAll(4,2)
list1.partition(4,2,listOf("a","b"))
The partition function originally in Kotlin returns Pair <List <T>, List <T >>
, so the usage is different.
partitionby.clj
(partition-by identity list2)
(partition-by #(> % 7) list2)
partitionby.kt
fun <T, R> Iterable<T>.partitionBy(function: (T) -> R): List<List<T>> {
if (count() == 0) return listOf()
return drop(1).fold(listOf(listOf(first()))) { acc, v ->
if (function(acc.last().last()) != function(v))
acc + listOf(listOf(v))
else
acc.dropLast(1) + listOf(acc.last() + v)
}
}
list2.partitionBy { it }
list2.partitionBy { it > 7 }
Recommended Posts