https://kotlinlang.org logo
Title
a

arekolek

07/04/2019, 12:24 PM
inline fun Foo.notMyFunction(block: Bar.() -> Unit) {
    bar.apply(block)
}

inline fun <R> Foo.myFunction(block: (Bar) -> R): R {
    notMyFunction {
        return let(block)
    }
    error("")
}
is there any reasonable way to implement
myFunction
given
notMyFunction
?
m

Marc Knaup

07/04/2019, 12:26 PM
Only when using an interface which declares
notMyFunction
. But you can't use
inline
then.
d

Dico

07/04/2019, 2:59 PM
return block()
insteas of let(block)?
a

arekolek

07/04/2019, 6:57 PM
let(block)
,
block(this)
, whatever, but mainly I’m wondering if it’s possible to get some value out of there without that
error("")
at the end reason was: using a function with similar signature in class initialization - can’t initialize properties inside the lambda, but could assign the property with result of
myFunction
m

Marc Knaup

07/04/2019, 7:38 PM
If you want the compiler to know that the
notMyFunction
invocation never returns you have to tell it that its lambda is called exactly once.
@UseExperimental(ExperimentalContracts::class)
inline fun Foo.notMyFunction(block: Bar.() -> Unit) {
	contract {
		callsInPlace(block, InvocationKind.EXACTLY_ONCE)
	}

	bar.apply(block)
}

inline fun <R> Foo.myFunction(block: (Bar) -> R): R {
	notMyFunction {
		return let(block)
	}
}
a

arekolek

07/04/2019, 7:54 PM
I guess it would be nice, but
notMyFunction
is not mine, so I’d have to request that feature. Still, even if it was added, would it be possible to get the value out of there, without defining
myFunction
? Assuming
Bar
has a
getBoolean
function:
class Baz(foo: Foo) {
    val spam: Boolean = foo.notMyFunction {
        // some magic to make apply work like let and return:
        getBoolean("spam")
    } 
}
m

Marc Knaup

07/04/2019, 7:57 PM
class Baz(foo: Foo) {
	val spam = with(foo) { lateinit var magic: String; notMyFunction { magic = "spam" }; magic }
}
k

karelpeeters

07/05/2019, 8:05 AM
If it has the right contract this just works:
@UseExperimental(kotlin.contracts.ExperimentalContracts::class)
inline fun Foo.notMyFunction(block: Bar.() -> Unit) {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }

    bar.apply(block)
}

fun main() {
    val foo = Foo()

    val spam: Boolean
    foo.notMyFunction {
        spam = getBoolean("spam")
    }
    
    println(spam)
}