I’m still experimenting with context parameters. I...
# functional
j
I’m still experimenting with context parameters. Is there a better way to do this?
Copy code
fun main() {
    with(
        with("World!") { someWork }
    ) {
        println(feature())
    }
}

context(dep1: String)
val someWork: () -> String
    get() = {
        "Hello $dep1"
    }

context(concat: () -> String)
fun feature(): String = "Feature: ${concat()}"
It works but I’m not fan of the nested `with`/`context` and that I have to wrap my functions in getters to be able to pass them around as parameters I tried to use a regular fun for
someWork
and
with("World!") { ::someWork }
but I got this error. > Callable reference to ‘context(dep1: String) fun someWork(): String’ is unsupported because it has context parameters. Is there a rule of thumb saying lambdas shouldn’t be used as context parameters? I tried this but it doesn’t work neither
Copy code
fun main() {
    val lambda: () -> String = with("World!") {
        ::someWork
    }
    println(feature(lambda))
}

context(dep1: String)
fun someWork(): String = "Hello $dep1"

fun feature(concat: () -> String): String = "Feature: ${concat()}"
> Inapplicable candidate(s): context(dep1: String) fun someWork(): String
y
Callable references for contextual declarations are simply not supported yet. Hence, your
::someWork
doesn't work right now, but it should eventually. Here's how I'd approach this btw: Make some
fun interface
for
concat
so that it's not just a function type. It's rather unusual to have function types and other "primitive-esque" types as contexts.
j
So you would replace
Copy code
context(concat: () -> String)
fun feature(): String = "Feature: ${concat()}"
with this?
Copy code
fun interface Feature() {
    operator fun invoke(): String
}

fun Feature(concat: () -> String) = Feature {
    "Feature: ${concat()}"
}
I’ve used
fun interface
a lot in the last years and I’m trying to see where context-parameters can play a role. There’s some boiler plate associated with
fun interface
as seen in the previous snippet and feels a bit overkill for small features that just combine a few building block functions
Especially when I only have one implementation of the interface and it’s used internally in a module.
y
Well, probably more like:
Copy code
interface Feature {
  val value: String
}
fun Feature(concat: String) = object: Feature {
  override val value = "Feature: $value"
}
But yes, on the right track.
I haven't seen this done yet, but the compiler has an extension point to allow a function call like:
Copy code
contextHere(foo)
to add a receiver that refers to
foo
. This is used in
DataFrame
for DSL shenanigans, but this here would be a very simple and natural use for it
j
interesting, do you have any reference of where it’s used in DataFrame? I’ll have a look and see how they use it.
y
On mobile right now, but I believe they override a function called "addNewImplicitReceivers*
👍🏻 1
You nerd-sniped me! https://kotlinlang.slack.com/archives/C0BJ0GTE2/p1760646677730459 Your example would thus be:
Copy code
with("World!")
with(someWork)
println(feature())