benleggiero
05/10/2018, 3:05 AMbenleggiero
05/10/2018, 3:07 AMkarelpeeters
05/10/2018, 7:22 AMoperator fun sequenceLiteral
go? Top-level somewhere?voddan
05/10/2018, 9:08 AMval b2 = [1, 2, 3] as MutableList<Int>
Something tells me this reuse of the as
operator will not go well with JB guysrrader
05/10/2018, 9:38 AMtakesAmbiguousType(["1", true, 3] as Set<Any>)
how this is better than
takesAmbiguousType(setOf("1", true, 3))
?nish
05/10/2018, 5:00 PM[["foo"] : ["bar", "baz"]]
like this outweighs the risk of mistaking { ["foo"] : ["bar", "baz"] }
for a functionnish
05/10/2018, 5:01 PMbenleggiero
05/11/2018, 12:19 AMbenleggiero
05/11/2018, 12:21 AMsyntaxLiteral
and called it like this:
val b2 = syntaxLiteral(1, 2, 3) as MutableList<Int>
benleggiero
05/11/2018, 12:24 AMas
. This applies to custom collections and generic types, too. All this while keeping the exact syntax of the sequence the same, something that isnāt really possible with the ___Of(
syntaxbenleggiero
05/11/2018, 12:32 AMfoo[bar]
means āIām accessing an item in a collectionā, foo[bar] = baz
means āIām changing an item in a collectionā, and @foo([bar, baz])
means āIām creating and passing an array collection to this annotationā. I am continuing this pattern by showing that [ foo : bar, baz : qux ]
mean āIām creating a dictionary collectionā, furthering the enforcement that square brackets mean collections.
Additionally, currently, curly braces mean scope. When there is an opening curly brace, you are entering a new scope and can take outer things in, and when there is a closing curly brace, the scope ends and everything local to it is destroyed.
Utilizing curly braces as dictionary delimiters muddies this concept, because by definition, everything in that dictionary is persisted and passed somewhere.benleggiero
05/11/2018, 12:32 AMilya.gorbunov
05/11/2018, 2:39 AMsequenceLiteral
operator defined for each of the standard collections, e.g. List
, Set
, Array
, Sequence
.
Now consider the operator functions like +
on collections that have overloads for different combinations of the first and second parameter types ā using collection literals as their parameters would be inherently ambiguous.
What overload did I mean in this expression:
collection + [element1, element2]
?
Is it Iterable + Array
, or Iterable + Iterable
, or Iterable + Sequence
?benleggiero
05/11/2018, 3:16 AMcollection.plus(sequenceLiteral(element1, element2))
. As with the entire rest of the language, you will have to differentiate it somehow, be it with as
, by saving the collection to an explicitly-typed variable first, etc.
I addressed this in the comments of the original gist: https://gist.github.com/BenLeggiero/1582a959592cadcfee2a0beba3820084#gistcomment-2547629ilya.gorbunov
05/11/2018, 4:35 AMmap
, filter
etc on a collection literal, without casting it first.voddan
05/11/2018, 7:54 AMbenleggiero
05/12/2018, 4:14 AMbenleggiero
05/12/2018, 4:16 AMsequenceLiteral("1", "2", "3").map { it.toInt() }
wonāt work. Which means ["1", "2", "3"].map { it.toInt() }
would work as wellilya.gorbunov
05/12/2018, 4:23 AMbenleggiero
05/12/2018, 5:35 AMlistOf
ilya.gorbunov
05/13/2018, 11:56 PM[1, 2, 3].map { }
case isn't different from takesAmbiguousType([1, 2, 3])
and the proposal says the latter should be resolved with casting.
It's an interesting idea to default to List/Map even for ambiguous expected types, but it should be examined with care, whether it could introduce unintuitive consequences.
Please either treat the ambiguity consistently in the parameter and receiver positions (and decide how should it be treated), or list both options in the "open questions" section of the proposal.benleggiero
05/14/2018, 12:13 AM[1,2,3].map {}
would map a List<Int>
, since that is the default type of a sequence literal. So it would be exactly the same as listOf(1,2,3).map {}
Maybe I should give examples, but I was imagining that takesAmbiguousType
as an overloaded method, with one taking maybe a Set and another taking maybe an Array (the exact types don't matter as long as none are List
), so the default type is not applicableilya.gorbunov
05/14/2018, 12:14 AM.map
extension is also overloaded for multiple receiver types (neither of them is List, the closest one is Collection or Iterable)benleggiero
05/14/2018, 12:28 AMmap
clearly applies to the default type, but the default type doesn't apply to takesAmbiguousType
, this is why casting and other type hints aren't necessary in the map example, but are in the ambiguity example.
I'll note this in the proposalkarelpeeters
05/14/2018, 12:33 AMbenleggiero
05/14/2018, 12:34 AMbenleggiero
05/14/2018, 2:40 AMfun takesAmbiguousType(x: Set<Int>) {}
fun takesAmbiguousType(x: Array<Int>) {}
takesAmbiguousType([1, 2, 3]) // Error: cannot resolve type; default sequence literal type List<Int> does not match any candidates
takesAmbiguousType([1, 2, 3] as Set<Int>) // OK
takesAmbiguousType([1, 2, 3] as Array<Int>) // OK
val y: Set<Int> = [1, 2, 3]
takesAmbiguousType(y) // OK
// Defined in stdlib: public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R>
public inline fun <T, R> map2(x: Iterable<T>, transform: (T) -> R): List<R> { /* ... */ }
val z = [1, 2, 3] // Inferred type is List<Int>
z.map { it.toString() } // Maps List<Int> to List<String>
map2(z) { it.toString() } // Maps List<Int> to List<String>
[1, 2, 3].map { it.toString() } // Maps List<Int> to List<String>; no type is given but default type List<Int> matches a map candidate
map2([1, 2, 3]) { it.toString() } // Maps List<Int> to List<String>; no type is given but default type List<Int> matches a map2 candidate
ilya.gorbunov
05/14/2018, 2:58 AMmap
has a couple of overloads, e.g. with Array
and Sequence
as receivers. Does it change the resolution result in the example above?
If it doesn't, consider the following overloads:
fooAnyOrSet(param: Any)
fooAnyOrSet(param: Set<*>)
fooAnyOrSet([1, 2, 3])
Is it an expected behavior that the first overload is selected in this case?gildor
05/14/2018, 10:43 AMrecommends that these existing functions be marked as deprecatedI am absolutely against such proposal about deprecation of existing builders, itās not clear how this change can improve language and no clear why we should do that, for example not clear what to do with method references to those methods
benleggiero
05/15/2018, 2:33 AMList<Int>
to fun fooAnyOrSet(param: Any)
, since the default type matches itbenleggiero
05/15/2018, 2:34 AMgildor
05/15/2018, 2:38 AMval list: List<String> = "some string".run(::listOf)
How can I do that without builder functions using only literals?
If builders would be deprecated this code will be marked as deprecated toobenleggiero
05/15/2018, 3:26 AMilya.gorbunov
05/15/2018, 4:31 AMlist1.zip(list2, ::Pair)
// or
".+".let(::Regex)
gildor
05/15/2018, 4:50 AMlistOf
hides implementation details, so you cannot do something like ::List
, only ::ArrayList
, but itās not what you wait from list builderudalov
"some string".run(::[])
š§voddan
05/15/2018, 5:40 PMvoddan
05/16/2018, 8:33 AMilya.gorbunov
05/23/2018, 1:02 PMbenleggiero
05/23/2018, 1:37 PMvoddan
05/24/2018, 6:52 AMbenleggiero
05/25/2018, 12:54 AM