I think non-static scope injection is very nice feature, it is heavily exploited in Kotlin for convenient and easy
way to define builders/dsl and prove to be really powerful thing.
It is build on top of Katlin’s extension methods/ extension functions / extension lambadas
And in fact it is really close to
But use rather “extension” instead of “implicit” word
So Kotlin’s
ThisArg.() -> ResultType
Should become something like
ThisArg `extension import =>` ResultType
using DSL Paradise notation, or alternatively I personally would prefer something like
// without regular arguments - similar to Kotlin's `ThisArg.() -> ResultType`
(@this @import ThisArg) => ResultType
// or with them - similar to Kotlin's `ThisArg.(RegularArg1, RegularArg2) -> ResultType`
(@this @import ThisArg, RegularArg1, RegularArg2) => ResultType
Also I think it could be very interesting to know that Kotlin also allows to resolve “scope injection clashes” via
marking different blocks/lambdas by labels: it is available as Qualified this expression
Brief demonstration of that Kotlin’s features may look like this:
Kotlin’s extension methods/functions/lambadas:
fun testExtensions() {
data class PointXY(val x: Int, val y: Int)
// extension method/function
fun PointXY.mullXY(): Int {
// first argument of extension method passed through `this`
assert(this is PointXY)
assert(this.x == x)
assert(this.y == y)
return x * y;
}
// extension filed / local variable / method argument - member of extension function type initialized with extension lambada
val addXY: PointXY.() -> Int = {
// first argument of extension lambada passed through `this`
assert(this is PointXY)
assert(this.x == x)
assert(this.y == y)
x + y;
}
// usage
val p0: PointXY = PointXY(10,6)
assert(60 == p0.mullXY())
assert(16 == p0.addXY())
}
Kotlin’s resolution of hidden names (Qualified this expression):
fun testExtensionsScopeResolution() {
data class PointXY(val x: Int, val y: Int)
data class PointYZ(val y: Int, val z: Int)
val pXY = PointXY(1,2)
val pYZ = PointYZ(3,4)
// Kotlin( `with(obj) {...}` ) == Kotlin( `obj.apply {...}` ) == Scala( `{import obj._; ... }` )
with(pXY) labelOuterLambda@ {
pYZ.apply labelInnerLambda@ {
// `x` and `z` resolves without clashes
assert(x == pXY.x)
assert(z == pYZ.z)
// `this` resolves to `pYZ` hover all outer `this`-es are also available via qualified notation
assert(this@labelOuterLambda == pXY)
assert(this@labelInnerLambda == pYZ && this == pYZ)
// ambiguity of `y` resolution can be resolved by labels, by default it resolved in nearest scope
assert(y == pYZ.y && y == this.y)
assert(this@labelInnerLambda.y == pYZ.y)
assert(this@labelOuterLambda.y == pXY.y)
}
}
}
So I think it would be nice if Scala has something similar or (something better). In my opinion without scope injection in Scala, Kotlin will look much better then Scala in this area.