Might be nice to declare extension methods without repeating the type

Was looking at some extension methods and properties I had declared and saw something like this:

fun SomeReallyLongTypeName.method1() { ... }
fun SomeReallyLongTypeName.method2() { ... }
val SomeReallyLongTypeName.property1: SomeType get() = // ...
val SomeReallyLongTypeName.property2: SomeType get() = // ...

And was thinking about the way Dart declares extension methods (Extension methods | Dart) and in Dart extensions are always declared in an extension block. So in Dart that would be:

extension MyExtension on SomeReallyLongTypeName {
    method1() { ... }
    method2() { ... }
    SomeType get property1 = // ...
    SomeType get property2 = // ...
}

which is easier to read with less boilerplate.

Would be nice if Kotlin had a similar capability to declare a block of extensions and not have to repeat the type name over and over.

9 Likes

This would be extra helpful if kotlin decides to accept the mutliple recievers KEEP.

4 Likes

What about using typealias to make the name shorter?

Yes using a type alias can make the name shorter, but still doesn’t address the root issue. For one thing you then have the cognitive load of having to know what type the alias is referring to. If you have a lot of extensions then that alias my be hundreds of lines away. It would be more convenient and easier to read if you could declare extensions as a block

To be honest the argument that the type alias might be hundreds of lines away is also an argument against this way of declaring extensions. After all the same could be said for the top of the extension block so that would be equally far away.

Anyways, I feel like this would be most feature would be most useful for a large number of extension functions/properties that can be written as 1 liners, maybe 2-3 lines. I could see this being useful for wrapper libraries around native or java libs. Once functions get larger however I don’t think that this would make much of a difference and might be even a disadvantage.

But that argument could also be made about the non-extension methods declared inside the class. The top of the class could be hundreds of lines away yet we don’t have a problem in that case because we are talking about a nested context which (not sure best how to describe it) is less cognitive load. After all they could have done it like C++ where the class name has to be a prefix on every class method, but I think we would agree the ability to just nest them is easier to read.

I am not suggesting that it be required to declare them in a block, but if it were possible it could improve readability. Any feature can also be abused to decrease readability.

1 Like

I use Swift often and I want this feature in Kotlin too.

In Swift it is simple:

extension String  {
    func method1() { self is String }
    func method2() { ... }
    var property: Int {  }
}

or a more complex one:

extension Array where Element == String //or Element: Protocol
 {
func getAll() { ... }
}

so I would suggest:

extension String  {
    fun method1() { this is String }
    fun method2() { ... }
    var property: Int get() = 42
}
2 Likes

In Dart there is an optional name for the extension block which is used for importing the extensions so you can import all the extensions with one import.

Based on my limited experience so far, I’m not sure how prevalent this use case is, let alone whether the prevalence/usefulness of a new feature balances out the increase in language complexity (if you have ever looked through a modern C# book, you may understand what I mean).

Anyway, at the moment I myself am not convinced that the benefits of brevity outweigh the benefits of readability and simplicity (though I guess that is ultimately for the Kotlin team to decide).

I am wondering though what the least ‘exotic’/‘surprising’ or most natural way to achieve this goal would be? ‘extension’, at the very least, does not seem a current keyword in Kotlin.

perhaps

with (String) {
fun f1() = 

}

may be better
 but if anyone has some more/better ideas about natural/easy to read/remember syntax, that may help to get this feature in.

1 Like

It doesn’t seem like a big deal, IMHO.

2 Likes

Is it a huge deal? No. But would be a nice reduction in boilerplate in some cases where you have multiple extensions on type with a long name.

As suggested, this issue was addressed by type alias.

1 Like

The extension interfaces are a huge deal and shortening the name of the receiver seems irrelevant in its scope. The idea of extension interface is to be able to declare an interface (not implementation) and be able to declare types as ones having some kind of extension interface implemented on them. It is more or less the idea of KEEP-87. It requires significant design efforts.

The other possibility, as @Wasabi375 mentioned is already available. You can declare an interface or an object with member extensions and apply this object with with method. There is also a section in the KEEP-176 discussion about providing class-level receivers. It would allow avoiding those long names inside the extension class. Of course in order to do it properly, one needs full multi-receiver mechanics. In my opinion, this way is much more flexible.

2 Likes

I posted a similar question, and no, this issue is not addressed by type alias. In the OSS world, I can’t tell how many times I’ve seen maintainers/designers slap a retort “this is by design”, without truly explaining the reasoning behind such a design (ternary operator, also see this for a non-Kt example), other than the obvious “I’m in the committee and you’re not”. Swift has already been mentioned, Scala can do this too using implicit class; what is being asked here is not dissimilar to using with.

In the OSS world: fork compiler repository and try to implement it yourself, rather than whimper about designers. And you will see how it’s not easy.

One reason, for example: you’ll need new keyword (‘extension’), what can break thousands of lines in existing code.

Also don’t forget about tests coverage.

Well I worded it as “might be nice” so I’m not going off and forking the compiler. It is not a given that it would use the word “extension”. There are ways to do it without introducing new key words or at least introducing them in a way that it is only treated as a keyword in a certain context, i.e. a soft keyword. Here are possibilities:

MyClass companion extension {
MyClass.extension {

I am not prescribing a certain syntax, just saying it is a nice to have.

Thanks for proving my point with a new instance of “designer syndrome”. In case you’ve not noticed, no one is whimpering here; if you’ve nothing new to add to the discussion, I’m sure you can find other things to do.

Guys, calm down. No one here said the reason for the current state is that it is “by design” and suggesting that doesn’t help your point. It just just makes people want to engage less with the topic. So far I’ve seen some possible alternatives to this suggestion and depending on the project they might be good enough. Also passive agressive suggestions like “Why don’t you just implement it yourself” don’t help.


I’ve seen many projects where this feature would basically do nothing at all so there is a good argument that it should be cut by the minus 100 points rule but then there are other projects where this could improve readability by a lot. I’m not sure if the percentage of projects where this is the case is big enough that this feature is necessary, but I’m open to adding it if there are enough people out there that like the idea. That said, you still need to convince the kotlin team because they need to implement it in the end. And only because they haven’t shared their reasoning they probably discussed this idea as an alternative to the current extension function syntax (when extension functions where first implemented) so they might already have an oppinion here.

3 Likes

Named extension scopes that simplify import seems like an interesting aspect to me. IDEA is sometimes very slow to discover extensions for auto-completion or for auto-import, especially for infix functions. A “star-import” would help the IDE to find the extensions.

Yes. And the best starting point is to write a KEEP that discusses usages and possible corner cases.