xxfast
01/03/2022, 11:16 PMfun <T> Foo(bar: T) = Unit
class <T> Bar(foo: T) // wont compile
or
fun Foo<T>(bar: T) = Unit // wont compile
class Bar<T>(foo: T)
Jacob
01/04/2022, 2:30 AMJacob
01/04/2022, 2:30 AMxxfast
01/04/2022, 4:45 AMdmitriy.novozhilov
01/04/2022, 7:57 AMval x: Base<T>
, so class declaration syntax is consistent with use site
On the other hand type parameter of function can be used as receiver type, so if declare T
after function name, that it can be referenced before declaration, which hurts readability of code:
fun T.foo<T>() {}
// vs
fun <T> T.foo() {}
Fleshgrinder
01/04/2022, 8:08 AMmcpiroman
01/04/2022, 11:00 AMcontext(T) fun<T> foo(){}
.
Otherwise I see every other point on why this should be the other way:
1.
declaration | usage
class Foo<T>(bar: Int) //name, type Foo<String>(1) //name, type
fun<T> foo(bar: Int) //type, name foo<String>(1) //name, type
2. The principle of Kotlin says the name is more important than types and parameters and should be first, but type parameters on functions go against that rule and thus often obfuscate the declaration.
3. With classes the order is more consistent: class
, name, type parameters, value parameters. Type and value parameters are both parameters and thus are next to each other. With functions it is fun
, type parameters, name, value parameters.
Transition from fun<T> foo() {}
to ``fun foo<T>() {}``would probably be impractical in general but I'd appreciate if both ways were made possible, maybe behind a compiler flag.xxfast
01/05/2022, 12:08 AMcontext()
proposal, the above point becomes obsolete. Only downside of naming the templates after the name is when there’s additional modifiers applied to the template type. for instance
context(T)
inline fun T.foo<reified T: Any>(): T
i can see this becoming less readable compared to declaring types upfront