Maybe we can share our first-hand experience with this.
In the 2000’s (long before Kotlin existed), we had designed and implemented a language inspired by C# or Java, with advanced first-class features for that time. We’ll not digress on this but interestingly, it had many Kotlin features. This is also why we love Kotlin so much.
Anyway:
Our collection literal was the much proposed and obvious [1, 2, 3]
. For the compiler, this was an anonymous collection type with an element type inferred from the provided elements.
The compiler would try to find an implicit conversion from this anonymous type to the expectedType
of the compiled Expression
. This expectedType
was usually a lvalue or the type of a method parameter participating in overload resolution.
In clear, all of the following was possible (and happening at compile-time):
Int[] array = [1, 2, 3];
auto array = [1, 2, 3]; // lvalue has no expectedType => collection is by default a typed array
List<Int> list = [1, 2, 3];
HashSet<Int> hashSet = [1, 2, 3];
// for this one, the parameterless ctor of MyTypeImplementingCollectionOfInt is called, then Collection<Int>.add is called for each element (this is to summarize)
MyTypeImplementingCollectionOfInt obj = [1, 2, 3];
void foo(List<Int> list) {
}
foo([1, 2, 3])
void bar(Set<Int> set) {
}
bar([1, 2, 3])
// etc...
For maps, the same general principles were followed and it went like this:
auto map = ["one": 1, "two": 2]; // // lvalue has no expectedType => collection is by default a HashMap<KT, VT>
HashMap<String, Int> map = ["one": 1, "two": 2];
MyTypeImplementingMapOfStringInt obj = ["one": 1, "two": 2];
// same for method calls, etc...
For maps, the often proposed brace syntax might look more natural but we had to resort to the bracket syntax (which wasn’t bad either) because of grammar conflicts with the lambda syntax (a lambda as last arg could be passed exactly as with the Kotlin “DSL” syntax).
Return on experience with volumes of code (the compiler itself was implemented in the language and totalled about 50k lines) was very satisfying wrt. clarity and expressiveness.
Implementation wasn’t too hard. IIRC, a few parsers tricks were needed here and there to lift ambiguities with the indeder syntax.
Let’s hope that Kotlin will feature a similar kind of grammar in the future!