https://kotlinlang.org logo
e

edrd

02/09/2022, 3:50 PM
[not sure this is the right channel so let me know if there's a better place] I'm trying context receivers and tried to write an alternative "scoping" function but it didn't work:
Copy code
class Logging {
  val logger = java.util.logging.Logger.getLogger("test")
}

context(Logging)
fun hello() {
  <http://logger.info|logger.info>("Hello")
}

fun <C, R> within(ctx: C, call: context(C) () -> R): R = call(ctx)

fun main() {
  within(Logging()) {
    hello() // Error: No required context receiver found: Cxt { context(Logging) public fun hello(): kotlin.Unit defined [...]
  }
}
Is this supposed to be this way or it's just something not yet implemented in the prototype version?
Changing
within
to use a standard receiver instead of a context receiver works, though.
Copy code
fun <C, R> within(ctx: C, call: C.() -> R): R = call(ctx)
However I wanted to try lambdas with multiple receivers so to implement
with
functions for more than one receiver.
o

Oliver.O

02/09/2022, 6:52 PM
Works for me:
Copy code
class Logger {
    fun info(message: String) {
        println("INFO: $message")
    }
}

class Logging {
    val logger = Logger()
}

context(Logging)
fun hello() {
    <http://logger.info|logger.info>("Hello")
}

fun <R> within(ctx: Logging, call: context(Logging) () -> R): R = call(ctx)

fun main() {
    with(Logging()) {
        hello()
    }

    within(Logging()) {
        hello() // Error: No required context receiver found: Cxt { context(Logging) public fun hello(): kotlin.Unit defined [...]
    }
}
The above seems to happen if context receivers are not enabled for the compiler. Could you try this
build.gradle.kts
?
Copy code
@file:Suppress("UNUSED_VARIABLE")

plugins {
    kotlin("multiplatform") version "1.6.20-M1"
    application
}

repositories {
    mavenCentral()
}

kotlin {
    jvm {
        compilations.all {
            kotlinOptions {
                jvmTarget = "1.8"
                freeCompilerArgs += listOf("-Xcontext-receivers")
            }
        }
        withJava()
    }
    sourceSets {
        val jvmMain by getting
        val jvmTest by getting
    }
}

application {
    mainClass.set("MainKt")
}
h

Hanno

02/09/2022, 8:24 PM
I tried sth very similar but with two context parameters and it worked when i moved the lambda into a local variable and provided the type explicitly. So it works, also autocompletion in the lambda and so on, but not with an inline lambda, thats why i think its a bug.
o

Oliver.O

02/09/2022, 10:00 PM
I had overlooked that I had removed the first type parameter from
within
. As soon as I re-introduce it (
C
), the error reappears. So yes, seems to be a bug.
🙏 1
a

Anastasia Shadrina

02/10/2022, 10:41 AM
Thanks for the report. I created the issue, looking into it.
👍 2
🙏 1
6 Views