Je recherche Kotlin alternative à:(cons 1 '(2 3))
Dans LISP ou1 : [2, 3]
Dans haskell ou1 :: List(2, 3)
dans scala,
(qui aboutissent tous à quelque chose comme [1, 2, 3])
afin que je puisse ajouter un élément à un List<T>
(ou à toute autre liste que vous pouvez proposer).
Ce sera aussi bien si on pouvait fournir O(1) head
et tail
alternatives Kotlin (je n'ai trouvé que first()
)
Toute classe qui implémente Deque
vous conviendra, par exemple LinkedList
:
val linkedList = LinkedList(listOf(2, 3))
linkedList.Push(1)
println(linkedList) // [1, 2, 3]
La création de listes via le constructeur LinkedList(listOf(2, 3))
dans de nombreux endroits peut être ennuyeuse, alors n'hésitez pas à écrire la méthode d'usine:
fun <T> linkedListOf(vararg elements: T): LinkedList<T> {
return LinkedList<T>(elements.toList())
}
// Usage:
val list = linkedListOf(2, 3)
list.Push(1)
println(list) // [1, 2, 3]
Je pense que le plus simple serait d'écrire:
var list = listOf(2,3)
println(list) // [2, 3]
list = listOf(1) + list
println(list) // [1, 2, 3]
Il n'y a pas d'implémentation tail
spécifique, mais vous pouvez appeler .drop (1) pour obtenir la même chose. Vous pouvez faire cela head\tail
plus générique en écrivant ces propriétés d'extension:
val <T> List<T>.tail: List<T>
get() = drop(1)
val <T> List<T>.head: T
get() = first()
Ensuite:
val list = listOf(1, 2, 3)
val head = list.head
val tail = list.tail
Quelques informations supplémentaires: fonction de queue de la liste Kotlin
Simple, enveloppez simplement l'élément à ajouter dans un List
puis utilisez l'opérateur +
(Ou List.plus()
) pour concaténer les deux Lists
:
val list1 = listOf(2, 3) // [2, 3]
val list2 = listOf(1) + list1 // [1, 2, 3]
Pour votre deuxième question, dans Kotlin 1.2 il y a:
List.first()
List.last()
Les deux sont O (1)
Si vous le faites souvent dans votre code pour une raison quelconque, envisagez d'ajouter une méthode d'opérateur d'extension telle que:
operator fun <T> T.plus(tail: List<T>): List<T> {
val list = ArrayList<T>(1 + tail.size)
list.add(this)
list.addAll(tail)
return list
}
Ensuite, votre code pourrait fonctionner comme Scala: 1 + listOf(2, 3)
Une autre façon d'obtenir le même comportement, plus courte mais sacrifie de la mémoire:
operator fun <T> T.plus(tail: List<T>): List<T> {
return mutableListOf(this).apply {
addAll(tail)
}
}
Pour être aussi proche de LISP que possible, envisagez d'utiliser une liste chaînée immuable.
Vous pouvez utiliser pcollections
val list = ConsPStack.from(listOf(2, 3))
val newList = list + 1
println(list) // [2, 3]
println(newList) // [1, 2, 3]
Tête:
list.first() // 1
list[0] // 1
(malheureusement, cette chose a besoin d'une allocation)
Queue:
list - 0 // [2, 3]
list.subList(1) // [2, 3]
Ça a l'air plutôt moche.
J'espère que nous aurons une meilleure API quand kotlinx.collections.immutable sera prêt. C'est un effort pour créer des collections immuables Kotlin standard (pas seulement celles en lecture seule que nous avons actuellement). Pour l'instant, ce projet est encore à un stade très précoce (je n'ai pas pu trouver de structure qui prend en charge un prépend/tête/queue efficace)