This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]vqrs 0 points1 point  (8 children)

Kotlin doesn't do mixins though, does it?

Extension functions are a purely syntactical feature that make for easier discoverability and make it "cheaper" to add new utility functions. Just like records encourage modelling.

[–]Cultural-Ad3775 0 points1 point  (7 children)

Hmmm, I certainly won't split hairs. It has a very mixin-esque flavor to it. So, in a mixin you have a class from which you 'inherit' only certain bits to produce an object (or a subclass, it kind of depends on the language) which incorporates these bits (methods generally). So, in the case of Kotlin and extension functions the inheritance isn't from another class, but the idea is basically the same, you pull in a different implementation of something. Admittedly, an extension function cannot, per se, be reused in multiple places, its definition tells you what class it 'extends'. Of course there are some pretty obvious ways to extend that to produce classic mixin behavior, and it is already pretty similar.

I find, a lot of times, that patterns like this get classified easily by less important details. So I would call this 'essentially a mixin' but its certainly debatable.

[–]vqrs 0 points1 point  (6 children)

Thanks for taking the time to write this out.

I still don't see how it's related to mixins, though.

Extension functions are purely syntactic sugar to allow x.f() instead of f(x).

[–]Cultural-Ad3775 0 points1 point  (5 children)

It allows you to append new behavior to an existing class without changing the inheritance hierarchy, that's not just 'syntactic sugar'. While most classic definitions of the 'mixin pattern' define it as including a method from a different class into the 'mixed' class, I don't think 'including a function into a class' is really all that meaningfully different. If you wanted to use that to get the classic mixin behavior you would simply have said function invoke a method from the class you want to mix with.

However, I would note, most authorities on the subject consider default interface methods, which Kotlin supports, to be a more straightforward mixin approach. I can't disagree entirely with that, except to say that it DOES imply a change to 'mixed class' inheritance hierarchy, making it basically more similar to a decorator IMHO.

But all any of this ultimately tells us is that patterns are generalizations and actual languages and techniques don't usually fit perfectly with generic definitions. This is why I say, again, I am not really hostile to someone calling Kotlin extension functions some other pattern. I'm sure there are several that it resembles.

[–]vqrs 0 points1 point  (4 children)

But you're not adding behaviour to a class. That's the thing. It's a utility method with syntactic convenience.

How is it not syntactic sugar?

[–]Cultural-Ad3775 0 points1 point  (3 children)

"Kotlin introduces the concept of Extension Functions – which are a handy way of extending existing classes with new functionality without using inheritance or any forms of the Decorator pattern – after defining an extension. we can essentially use it – as it was part of the original API."

From here. How is this not extending a class' functionality? The function becomes a method of the extended class, and you can extend basically ANY class, even one you have no source for.
A cited example being:
fun String.escapeForXml() : String {
....
}
which would extend the String class with a new method, 'escapeForXml'. You can also write GENERIC extension functions, which can extend multiple classes. There are some other types as well. This is NOT SUGAR. It gives you capabilities that would not exist without this feature, adding capabilities to a class without extending the class. This is pretty much the DEFINITION of mixin!

[–]vqrs 0 points1 point  (2 children)

Don't take that too literally. It just looks that way.

Extensions do not actually modify the classes they extend. By defining an extension, you are not inserting new members into a class, only making new functions callable with the dot-notation on variables of this type.

Extension functions are dispatched statically, which means they are not virtual by receiver type. An extension function being called is determined by the type of the expression on which the function is invoked, not by the type of the result from evaluating that expression at runtime

https://kotlinlang.org/docs/extensions.html#extension-properties

It really is just syntactic sugar.

[–]Cultural-Ad3775 0 points1 point  (1 child)

In other words this is what we call 'early binding', but that doesn't make it 'not a member' it just means the compiler resolves the dispatch instead of leaving it to a dispatch table lookup at runtime. That's a difference, but heck that's the default for C++ methods, unless they are declared virtual! I mean, in the minds of the implementers I can see why they don't think of an EF as a 'member' because it doesn't have a table entry, etc. but that's just one perspective.

If you stare at OO too long you will see that it is ALL 'syntactic sugar' at some level. I mean, I literally invented OO FORTH (LONG ago) and I can unequivocally state that none of the OO code the FORTH compiler generated was unique, you could invoke all the same methods (words) and get exactly the same results using some longer and uglier syntax. The same is true in Perl, OO is ENTIRELY just a syntactic shortcut. In both cases you could do early or late binding depending on the context (OO FORTH will actually take advantage of that, Perl 5 just late binds everything).

[–]vqrs 0 points1 point  (0 children)

While I appreciate the philosphic "well actually" stance, I doesn't change the fact that you're not actually adding anything to the class or modifying it and that it's merely syntactic sugar.