sanf0rd
03/12/2018, 3:50 PMwhen()
with enums as much expressive as it is with a sealed class
benleggiero
03/14/2018, 3:48 PMAregev2
03/14/2018, 5:01 PMguenther
03/15/2018, 6:13 AMcaret
. Is there anything against this? (e.g. operator Int.caret(x: Int): Int = Math.....
)Slackbot
03/15/2018, 2:46 PMguenther
03/16/2018, 6:22 AMClass::function.name
literal a compile-time-constant?
This would really help in situations where a name for an annotation is actual a function-name like in JUnit-Parameterized-Tests:
object CalculatorTest {
@ParameterizedTest
// @MethodSource(value = CalculatorTest::multiplyNumberProvider.name) // HERE IT WOULD HELP
@MethodSource(value = "multiplyNumberProvider") // this sucks
fun `multiplication of two numbers (with params)`(num1: Int, num2: Int, expected: Int) {
...
}
fun multiplyNumberProvider(): Stream<Arguments> = ...
}
benleggiero
03/19/2018, 2:37 AMhttps://i.imgur.com/I7c9RMw.png▾
christopher
03/21/2018, 3:19 PMdeviant
03/23/2018, 2:36 PMcedric
03/25/2018, 10:30 AMnull
as false
is pretty intuitive. Kotlin by design avoids implicit conversions as much as possible, which is why that code is invalid but I don't think it would lead to bugs or hard to read code to silently convert a null
Boolean
to false
Fedor Bobin
03/30/2018, 7:51 AMhttpClient.get<Type>(...): Type <------ return type is handled from reified generic parameter
interface JsonSerializer {
suspend fun read(type: KClass<*>, content: IncomingContent): Any <<------ and handled type is used to instantiate object
}
If I pass List<MyObject> as a type parameter, I silently get List of garbage because reified generics does not include inner parameters and only List<*> will be passed to JsonSerializer.read(...)
I am wonder why not:
1) either: do not allow to pass classes with inner generics to reified methods
2) or: pass something different then just KClass that supports chain of genericsmekarthedev
03/30/2018, 6:53 PMbenleggiero
03/31/2018, 3:05 PMSlackbot
04/01/2018, 9:46 AMstephanc
04/16/2018, 1:06 PMbob?.department?.head?.name ?: "meh"
There is something like this:
bob.department.head.name ??: "meh"
cedric
04/16/2018, 6:48 PMnull
. I understand that’s the point of the operator, but I think it drifts away from Kotlin’s approach of staying away from implicit behaviors.poohbar
04/16/2018, 6:52 PM?.
operator actually works similarly. You do not have to repeat the question mark in the rest of the chain.
I thought the Kotlin approach was annoying at first but now it makes more sense to me than the C# approach and I have no need for a super elvis either.stephanc
04/17/2018, 7:29 AM.
@dalexanderstephanc
04/17/2018, 8:28 AM?
, at least there is scoping functions as well that limits this.poohbar
04/17/2018, 12:13 PM!!
on .min()
or .max()
calls where I know the collection is not empty. I kind of wish we had a NonEmptyList
that would return non-nullable types from such functions. Do you guys have a better way to handle this?karelpeeters
04/22/2018, 11:22 AMlist?[6]
would be cool as well.poohbar
04/26/2018, 8:31 PMsendilkumarn [JHipster]
04/30/2018, 2:04 PMweb assembly
karelpeeters
04/30/2018, 4:59 PM.int
if the standard way is too long.eddie
05/01/2018, 4:31 PMguenther
05/05/2018, 5:46 PMclass
with an extension property
using delegation. Of course only, when the delegated object (in this case the map) is accessible.
class Foo(val map: MutableMap<String, String> = mutableMapOf()) {
var bar1: String by map
}
var Foo.bar2: String by map
guenther
05/05/2018, 6:09 PMdimension val Int.px: MyDimensionedNumber get() = MyDimensionedNumber(this, "px")
dimension operator val Int.unaryRem: MyDimensionedNumber get() = MyDimensionedNumber(this, "%")
Then instead of using things like:
100.px
100.pct
This can be done:
100px
100%
Caleb Allen
05/07/2018, 10:47 PMclass ResponseHandler{
fun handle(success: Response.Success) {}
fun handle(error: Response.ErrorB) {}
fun handle(error: Response.ErrorA) {}
}
fun getResponse(): Response{
val r = Random()
return when (r.nextInt(3)) {
0 -> { Response.Success() }
1 -> { Response.ErrorA() }
2 -> { Response.ErrorB() }
else -> { throw IllegalStateException() }
}
}
And then calling
ResponseHandler().handle(getResponse())
This will not compile. The same effect can be achieved using if I implemented a method taking a Response
parameter like so:
fun handle(response: Response) = when (response) {
is Response.Success -> { handle(response) }
is Response.ErrorA -> { handle(response) }
is Response.ErrorB -> { handle(response) }
}
Is it possible for the compiler to resolve the type for me? Given that all possible types are handled, similar to when
benleggiero
05/08/2018, 4:16 AMbenleggiero
05/10/2018, 3:05 AMbenleggiero
05/10/2018, 3:05 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 functionbenleggiero
05/11/2018, 12:19 AMsyntaxLiteral
and called it like this:
val b2 = syntaxLiteral(1, 2, 3) as MutableList<Int>
as
. 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(
syntaxfoo[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.ilya.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 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 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 itgildor
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
05/15/2018, 3:35 PM"some string".run(::[])
:trollface:voddan
05/15/2018, 5:40 PMilya.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