mikehearn
05/12/2021, 2:53 PMjw
05/12/2021, 2:58 PMlistOf(1, 2, 3)
is not "a lot more verbose" than [1, 2, 3]
, especially since this form also scales to arbitrary collection types whereas a literal syntax does not.mikehearn
05/12/2021, 3:10 PMjw
05/12/2021, 3:23 PMjw
05/12/2021, 3:23 PMfn
instead of fun
. Saves a whole character.mikehearn
05/12/2021, 3:28 PMjw
05/12/2021, 3:29 PMjw
05/12/2021, 3:30 PMmikehearn
05/12/2021, 3:32 PMjw
05/12/2021, 3:34 PMjw
05/12/2021, 3:35 PMRoukanken
05/12/2021, 3:39 PMmikehearn
05/12/2021, 3:41 PMval a = [1, 2, 3]
-> a is List<Int>
. val a: ArrayList<Int> = [1, 2, 3]
etc. When the target type is a platform type, make it a mutable list because the distinction is irrelevant for Java anyway. Etc.dmitriy.novozhilov
05/12/2021, 3:48 PMWhy not-> a isval a = [1, 2, 3]
List<Int>
Array<Int>
, IntArray
or Set<Int>
?mikehearn
05/12/2021, 3:50 PM[x]
is already assigned to be Array
when used in annotation context, and it would be surprising for it be an ordered collection in one context by default but a set in another. Why List and not Array, because (on the JVM at least) lists have more features and are more widely used than arrays.Roukanken
05/12/2021, 3:52 PMList<T>
), and for all other ones no:
val a = arrayListOf(1, 2, 3)
val b: ArrayList<Int> = [1, 2, 3]
you can already see difference in 5(?) characters here
I guess it would be worth for deeper collections, but otherwise these functions imho top itdmitriy.novozhilov
05/12/2021, 3:54 PMoperator
function? Or maybe such classes should be marked with some annotation or inherit specific interface? And what about creating such builders for existing classes
- what are resolution rules of [x, y, z]
in presence of custom and default (from stdlib) collection builders?Roukanken
05/12/2021, 3:55 PMval a = arrayListOf(
arrayListOf(1, 4, 7),
arrayListOf(2, 5, 8),
arrayListOf(3, 6, 9),
)
val b: ArrayList<ArrayList<Int>> = [
[1, 4, 7],
[2, 5, 8],
[3, 6, 9],
]
mikehearn
05/12/2021, 3:55 PMoperator fun
would be more in keeping with the way existing features like destructuring work.mikehearn
05/12/2021, 3:56 PMval a = [1,2,3]
then there's nothing to call the operator fun on. But then, the language can simply have a fixed default type in that case (like List<T>
)mikehearn
05/12/2021, 3:57 PMoperator fun Set<T>.fromLiteral(vararg values: T)
or words to that effect. That would mean the answer to the second question becomes the same as the resolution rules for extension functions, which seems reasonable.dmitriy.novozhilov
05/12/2021, 3:58 PMmikehearn
05/12/2021, 3:59 PMdmitriy.novozhilov
05/12/2021, 4:01 PMoperator fun Set<T>.fromLiteral(vararg values: T)
, but it should be look something like that: operator fun fromLiteral(vararg values: T): Set<T>
. This shows another problems of this feature:
- not very intuitive way to declare collections builders
- requirement of function overloading by return type (because otherwise you can not have builders for List<T>
and Set<T>
in same package)mikehearn
05/12/2021, 4:05 PMop fun Set<T>.fromLiteral(vararg values: T): Set<T>
would make sense and avoid any overloading issues, right? The JVM can already distinguish methods by return type so at least there, it would not seem difficult to compile to an unambiguous class.Roukanken
05/12/2021, 4:23 PM{ key1 to value1, key2 to value2 }
because default would assume it's Set<Pair<K, V>>
and not Map<K, V>
as expected
Might change it (for example to { key: value }
) but that then won't be entirely consistent with all the other stuffmikehearn
05/12/2021, 4:41 PMoperator fun Map<K, V>.fromLiteral(vararg pairs: Pair<K, V>) = mapOf(*pairs)
then req.headers = [ "Content-Type" to "text/html", "Cookie" to "..." ]
mikehearn
05/12/2021, 4:44 PM[ ..., ... ]
is shorthand for invoking an operator function on the namespace of whatever the target type is, with List being a default, allows for quite reasonable and intuitive syntaxes in many cases. It's also quite similar to how operator fun get
works, which is nice symmetry.mikehearn
05/12/2021, 4:45 PMval a = [ "first" to 1, "second" to 2 ]
what you get is not a map but rather a list of pairs, which is probably a less useful default.mikehearn
05/12/2021, 4:46 PMmapOf()
to disambiguate what you meant.edrd
05/12/2021, 11:11 PMmutableListOf
and listOf
vs []
, the former expresses much more intention, which is important when reading code. Whenever I see a mutable collection, I read the code extra carefully to make sure such mutability is not a source of bugs or weird behaviors. Now, in these other "less verbose" languages, []
means mutable collections, and I think that's a bad default.
One may argue that we can have []
as immutable (or read-only) by default, but what about when we want a mutable collection? Then declaring val x: MutableList<Int> = [1, 2, 3]
is not a big win over val x = mutableListOf(1, 2, 3)
if the concern is verbosity.
The type inference stuff also concerns me. Suppose I have:
fun process(list: List<Int>) { ... }
fun execute() {
process([1, 2, 3])
}
and then process
changes to list: MutableList<Int>
. Code will compile fine, but should it? (not a rhetorical question)
The case with annotations is fine because it's always constant, so a default can be safely chosen.edrd
05/12/2021, 11:16 PMJordan Stewart
05/13/2021, 8:48 AMilya.gorbunov
05/13/2021, 11:21 AM(e.g. not on roadmap)Regarding the roadmap, it covers only our relatively short-term plans, that's why collection literals are not there. But it's wrong to say that it doesn't attract our interest. We told that we were looking at collection and data literals at Kotlin 1.4 Event for example: Our latest vision of how collection literals could look in Kotlin is summarized in this issue: https://youtrack.jetbrains.com/issue/KT-43871
ephemient
05/16/2021, 1:21 AMoperator fun <T> List.Companion.get(vararg elements: T) = listOf(*elements)
List[1, 2, 3]
but there's no List.Companion
(https://youtrack.jetbrains.com/issue/KT-11968)gildor
05/27/2021, 9:46 AMList[]
is somehow better than listOf()
I also saw code where people do:
operator fun <T> L(vararg elements: T) = listOf(*elements)
L[1, 2, 3]
Quite craze for me, but if you want to save a few characters 🤷Roukanken
05/27/2021, 9:48 AMlistOf
gildor
05/27/2021, 9:53 AMJolan Rensen [JetBrains]
05/28/2021, 12:26 PMarrayOf(arrayOf(), arrayOf())
can become a hassle. Personally, I think a solution could be to allow operator fun get()
to be called without explicitly typed receiver (like this[]
). That would mean you could type something like this:
val my2dArray: Array<IntArray> = buildArray {
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
}
Currently, if you really want it, something like this is already possible:
val my2dArray: Array<IntArray> = buildArray {
a[a[1, 2, 3],
a[4, 5, 6],
a[7, 8, 9]]
}
Actually, is there a YouTracks issue for this?Nir
05/30/2021, 6:27 PMNir
05/30/2021, 6:28 PMNir
05/30/2021, 6:28 PMNir
05/30/2021, 6:29 PMNir
05/30/2021, 6:30 PMelizarov
05/31/2021, 12:01 PMNir
05/31/2021, 2:00 PM