Hello! Is there a reason why I should write my cod...
# arrow
s
Hello! Is there a reason why I should write my code using extension functions, not regular member ones? I understand that they are resolved in compile-time, is this it? Extension functions allow the compiler to build and optimise the whole flow rather than treat the code as a set of objects that can interact with each other? Or is it just a question of style?
r
hi @Sergei Zubov, It’s just a question of style.
🚀 1
🙏 1
Both extension functions and members functions are similarly resolved by the compiler. All declarations and expressions are resolved at compile time. The fact you write something as an extension does not really optimize any kind of flow in the compiler AFAIK. It’s just a question on how you want to treat scoping in code when you would choose an style over other.
s
Thank you! So, we can use instance-based DI, like the one from Spring? The need to instantiate objects on the fly won't affect anything?
r
Polymorphism and by extension polymorphic Extension functions whether they are based on sub-types or generics with type bounds are not opinionated as to what instantiation strategy you use. For example
Copy code
interface Persistence
class LocalPersistence : Persistence

fun Persistence.save(): Unit = TODO()

val singletonPersistence = LocalPersistence()
object TestPersistence : Persistence
fun prototypePersistence(): Persistence = LocalPersistence()

singletonPersistence.save()
TestPersistence.save()
prototypePersistence().save()
Essentially you are stating here that
Persistence
is a dependency and you can use
save
if you have
Persistence
in context. In this example here you can see composition and another example that uses type bounds to add capabilities to each function in terms of accessing more than one dependency. This can be further simplified with context receivers when they land in Kotlin. https://gist.github.com/raulraja/97e2d5bf60e9d96680cf1fddcc90ee67
the gist is quite old so don’t try to compile it with the latest arrow version, it’s the concept I wanted to share
s
Also, extension functions, together with regular member functions, are great for functional modelling. Eg implement an interface with your specific model implementation and implement your extension functions as your "laws", ie code that'll remain the same no matter what actual implementation is used for the interface they extend.
👍 1
s
Great example, thank you. I ended up following this - https://www.pacoworks.com/2018/02/25/simple-dependency-injection-in-kotlin-part-1/. It works well, scopes can be hidden with modules, everything is easily mockable.
Thanks Anton, now I have another approach to think about😄
🙂 1
t
There is another use for extension functions and that is an API projection
Copy code
suspend fun <ENTITY : Any, TABLE> EntityRepository<ENTITY, TABLE, *>.listIntersecting(
    dtStart: LocalDateTime,
    dtEnd: LocalDateTime,
    andOp: Op<Boolean> = Op.TRUE,
): Either<Throwable, List<ENTITY>>
        where TABLE : EntityTable<ENTITY>,
              TABLE : HasStartTimeColumn,
              TABLE : HasEndTimeColumn =
    Either.catchAndFlatten {
        table.select {
            (table.dtStart lessEq dtStart and (table.dtEnd greaterEq dtStart))
        ...
    }
now this function can be called on any repository over a table that as StartTimeColumn and EndTimeColumn
r
Here is another one more example up to date from @simon.vergauwen https://gist.github.com/nomisRev/1f91710ebec1709d4ce8059812482624