# Arrays-2.0, multiple varargs and collection literals

**URL:** <https://discuss.kotlinlang.org/t/arrays-2-0-multiple-varargs-and-collection-literals/4951>\
**Category:** Language Design\
**Created:** [October 11, 2017, 4:29pm UTC](https://discuss.kotlinlang.org/t/arrays-2-0-multiple-varargs-and-collection-literals/4951 "2017-10-11T16:29:06Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![160R](https://avatars.discourse-cdn.com/v4/letter/1/76d3ee/32.png) [@160R](https://discuss.kotlinlang.org/u/160R)\
**Post date:** [October 11, 2017, 4:29pm UTC](https://discuss.kotlinlang.org/t/arrays-2-0-multiple-varargs-and-collection-literals/4951/1 "2017-10-11T16:29:06Z")

</div>

Hello,

I’m very big fan of Kotlin and it’s syntax improvements over Java (such as _zero-boilerplate delegation_ and _zero-boilerplate singletones_).

Recently I got interested in _zero-boilerplate builders_.  
I believe that builder pattern exists to overcome following language limitations:

- lack of named arguments
- lack of default and optional arguments
- lack of multiple vararg arguments

And when first two limitations don’t exists in Kotlin I’ll try to resolve third.

Also I want to share idea how to implement collection literals.  
It’s separate feature, but have common component with vararg - arrays.

Arrays - will be focus of this article.

* * *

NOTE:

Maybe this plan is too complex or idealistic to be implemented.  
I split it to parts and some can be skipped\changed to preserve backwards compatibility or keep simplicity.  
At least if it inspire someone I’ll be happy.

Also my English is weak. Sorry about that

* * *

These are steps to do:

1. Rename `Array<T>` to `[T]`.

- because it makes array types _special_ like lambda types and it’s important on next steps
- it should look like this:

```auto
   val arrayDeclarationExample: [String]? = null
   val genericsProjectionsExample: [out String]? = null
   val ThreeDimensionalExample: [[[Int]]]? = null
   fun arrayParameterExample(array: [Byte?]) { }
   fun arrayInLambdaExample(block: (() -> [Long])) { }
   fun arrayInLambdaExampleReceiver(block: [Char].(([Char]) -> Unit) { }
   fun getStringArray(): [String] = ["String"]
   fun getIntArray() = [1]

```

1. Imlement `array literals`

- because it’s useful, wanted feature and it’s required on next steps
- proposed syntax is:

```auto
   val arrayLiteralExample = ["hello", "array"]
   val arrayLiteralExampleEmpty: [String] = []
   val arrayLiteralExampleThreeDimensional = [[[]], [[], []], []] //Any
   arrayParameterExample([42, 42])
   arrayParameterExample([])
   arrayInLambdaExample({ [] })
   arrayInLambdaExample({ [1, 2, 3] })
   arrayInLambdaExample { [1, 2, 3] }

```

1. Introduce `vararg arrays` instead of `vararg keyword`

- difference with varargs is that multiple vararg array arguments are allowed
- difference with arrays is that spread operator is required when array is created not in place
- Java varargs are converted to Kotlin vararg arrays automatically
- syntax should look like this:

```auto
   fun takesVarargArrays(a: vararg [Int], b: vararg [String])
   takesVarargArrays([1,2,3], [])
   takesVarargArrays(*getIntArray(), *getStringArray())

```

1. Relax syntax rules on vararg arrays to encourage users to use them in right places

- 1) vararg array arguments are default to empty arrays
- 2) braces on vararg array literal can be ommitted with single value
- and here are examples of legal expressions:

```auto
   takesVarargArrays()
   takesVarargArrays([])
   takesVarargArrays(b = [])
   takesVarargArrays(a = 1)

```

1. Apply _last argument convention_ for vararg array literals

- it works well for higher-order functions and makes Kotlin so awesome!
- also, it’s known and simple rule - no re-inventing the wheel, no surprises
- example

```auto
   fun lastArgumentConventionExample(dummy: String, a: vararg [Int]) { }
   lastArgumentConventionExample("text") [1, 2, 3, 4, 5]
   fun lastArgumentConventionExampleSingle(a: vararg [Int]) { }
   lastArgumentConventionExampleSingle [1, 2, 3, 4]

```

- collection literals now are very easy to implement, some are already implemented

```auto
   val listExampleGeneric = listOf<String> []
   val listExampleGenericSameAsPrevious = List<String> []
   val mapExample = Map [
         0 to false,
         1 to true
   ]
   val arrayListExample = ArrayList ["constructor", "inferred", "from", "JVM"]
   val arrayListExampleHint = ArrayList(4) [""]
   val rxExample = Observable.just [1, 2, 3]

```

1. Update _index access_ and _index assign_ operators to work after dot

- this should resolve some inconsistencies with changes introduced in previous steps
- example

```auto
   val indexAccessExample = arrayListExample.[0]
   ArrayList[1, 2, 3].[0] = 3
   Map<String, Any>[].["key"]

```

And result should be following:

```auto
annotation class AnnotationExample(val args: vararg [String])
@AnnotationExample["hello", "annotation"]
@get:AnnotationExample
@set:[AnnotationExample(args = "single")]
val annotationUsageExample = 1

class WithoutBuilder(
   val name: String,
   val array: [String],
   val optional: Int?,
   val variadic: vararg [String],
   val nested: [WithoutBuilder]
)
val withoutBuilderExample = WithoutBuilder("exampleParent",
   array = [],
   optional = 100,
   nested = WithoutBuilder("exampleNested"
      array = ["", "", ""],
      variadic = "single",
      nested = WithoutBuilder("exampleNestedDeep", [], 100,
         variadic = ["a", "b", "c"],
         nested = WithoutBuilder("exampleNestedLast",
            array = getStringArray(),
            variadic = *getStringArray())
      )
   )
)

```

---

<div class="post-metadata">

**Author:** ![madmax1028](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/madmax1028/32/3335_2.png) [@madmax1028](https://discuss.kotlinlang.org/u/madmax1028)\
**Post date:** [October 11, 2017, 6:23pm UTC](https://discuss.kotlinlang.org/t/arrays-2-0-multiple-varargs-and-collection-literals/4951/2 "2017-10-11T18:23:28Z")

</div>

Actually I also would like to have array literals, just like in vanilla Java.

But regarding varargs a case is a little more complex:

```auto
fun takesVarargArrays(a: vararg [Int], b: vararg [String])
takesVarargArrays([1,2,3], [])

```

This one maybe seems quite oblivious, because you have concrete types.

But if you had changed it to this:

```auto
fun takesVarargArrays(a: vararg [Any], b: vararg [Any])
takesVarargArrays([1,2,3], [])

```

Then it becames ambigous wherever you want to pass a whole arrays as arguments or just their values. That’s why spread operator was introduced in Kotlin.

```auto
takesVarargArrays(*[1,2,3], *[])

```

But even this one is off, because you can spread multiple arrays into one vararg argument, so this one is also wrong, because in Kotlin if you write:

```auto
fun takesVararg(vararg a: Int)
takesVararg(1, *intArrayOf(2, 3, 4), 5, *intArrayOf(6, 7, 8))

```

Then is’s a completelly valid code which applies only to a single vararg argument 🙂

Last argument convension seems a little off to me, because if you write code in classic braces you have almost indentical amount of characters. Another problem is that it becames ambigous in some cases. If you returned array/collection from such function:

```auto
fun varargFunction(vararg numbers: Int) = numbers
varargFunction [1]

```

Now it’s a problem wherever you would like to pass value `1` as argument, or you want to call array returned by it’s index 🙂

Collection literals also don’t seem so attractive, because you already have functions in Kotlin which are useful enough for the most tasks. And there are also immutable variants. Here you are forced to operate on mutable collections.

As for the rest I don’t have an opinion 🙂

---

<div class="post-metadata">

**Author:** ![160R](https://avatars.discourse-cdn.com/v4/letter/1/76d3ee/32.png) [@160R](https://discuss.kotlinlang.org/u/160R)\
**Post date:** [October 12, 2017, 1:21am UTC](https://discuss.kotlinlang.org/t/arrays-2-0-multiple-varargs-and-collection-literals/4951/3 "2017-10-12T01:21:29Z")

</div>

Okay,

some things are described bad due to my language limitations and some because I was trying to make proposal as simple as possible.  
So, need to clarify: vararg arrays are always passed as values and always created and declared explicitly.  
Here is example of behavior in case with array of `Any` you described:

```auto
fun takesVarargArrays(a: vararg [Any], b: vararg [Any]) 
    = println("a.size=${a.size}, b.size=${b.size}")

takesVarargArrays([[]], []) // a.size=1, b.size=0

```

On JVM when you passes whole array to varargs of `Any` you wraps array in array and passes it to function - _here it’s visible_.  
Outer array is vararg array used in function. Inner is an content of vararg array.  
Everything is straightforward.

* * *

If we go deeper, we can even get rid of `*` and `vararg` operators (that are just syntax sugar for arrays).  
I.e. Rust language don’t have varargs and I really like this decision  
because that same functionality can be achieved with following syntax:

```auto
fun takesArray(a: [Int] = []) 
    = println("a.size=${a.size}")

takesArray() // a.size=0
takesArray([]) // a.size=0
takesArray([1] + [1, 2]) // a.size=3
val array = [1, 2]
takesArray(array) // a.size=2
val value = 1
takesArray(array + [1, value]) // a.size=4

```

that don’t introduces additional complexity to parser and not confuses novices with extra operators.  
As you see, spreading multiple arrays can be easily replaced with array concatenation.

Problem is only that currently Kotlin creates defensive copy of array with `*`, and I’m not sure if it’s safe to not create it.

* * *

About last argument convention: it makes syntax even simpler:

```auto
takesArray [1, 2, 3]

```

and it’s not ambiguous (see step **6.** sorry if it was unclear before edit).  
It should simplify collection creation and building complex objects.

As for collection factory functions, you will be able to use them in this way:

```auto
listOf [1, 2, 3]
mutableListOf [1, 2, 3]
mapOf [
    1 to 2,
    2 to 3]

```

But they don’t look like collection literals (on top of [Kotlin feature survey](https://blog.jetbrains.com/kotlin/2017/06/kotlin-future-features-survey-results)).  
I propose to deprecate these functions and construct collections like these:

```auto
List [1, 2, 3]
MutableList [1, 2, 3]
Map [
    1 to 2,
    2 to 3]

```

Don’t sure it will be implemented as constructors or uppercase functions…  
But same collection types remain and immutablility will be on first place (confusing example in **5** also updated).

* * *

Thanks,  
I’m really didn’t know about multiple arrays spreading and missed case of `[Any]`,  
good catch!
