Hey, is anyone aware of a way to pass context to t...
# getting-started
d
Hey, is anyone aware of a way to pass context to the getValue method of a property delegate? E.g. to enable something like this:
Copy code
val uppercased by Uppercased()

with ("two") {
    println(uppercased) // "TWO"
}

with ("three") {
    println(uppercased) // "THREE"
}
I tried experimenting with context receivers on delegate's
getValue
but it only uses the context from the
by Uppercased()
line
2
youtrack 1
g
I guess it's impossible because getter is defined the moment it is declared (if we are talking about local variables; in case of properties the statement can be false because we can specify receiver and/or context receivers, so getter is defined only in usage place). So getter can not depend on context. But you can either declare a non-local variable with receiver/context or add property to the type of
uppercased
like this:
Copy code
context(String)
val Uppercased.value get() = this@String.uppercase()

...

with("two") {
    println(uppercased.value)
}
d
Although it is true the getter is defined in the declaration, getValue on the getter could take a context argument and the transformed code could pass this through when the variable is dereferenced and getValue is called, so the functionality is not out of the question. It is a shame that getValue can't be parametric at the call site the same way get() can be, but it seems I might be expecting too much from property delegates
y
Yes it really is quite annoying. I think it should work on callsite as you suggest, especially because if one wanted to "bind" a context when the variable is defined by delegation, one can just have the context receiver on
provideDelegate
d
Agree Youssef - feels like a missed opportunity
y
I'm pretty sure that they could still change the behaviour because 1) context receivers are experimental 2) practically no one would be relying on that behaviour and 3) the compiler can statically detect all cases where this unexpected behaviour was used
a
I agree, there have been many instances where i’ve wanted do to use context on the getValue methods but can’t because it has to be in scope when it’s declared instead of when it’s called, which hasn’t really made sense to me
w
I think this issue should definitely be on YouTrack. If context receivers allows adding additional receivers on places where you can currently only use a single receiver, this is a place they forgot. Since you can still use regular receiver syntax for single receivers (image 1) or hack it as members into your own types (image 2).
K 1
d
Wout, that is a nice suggestion - I hadn't considered that. I was hoping for receiver on
getValue
itself so I can declare like
val uppercased by ...
without the
String.
at the declaration site. Still, pretty close to what I need!
y
I think your 2nd example is a stronger reason as to why contexts should be resolved at call site and not definition site. The
PrefixedUpperCase
value is only provided at call site there, and so contexts should work the same way. I'll make an issue when I get the time, but anyone's free to make it.
w
Yeah, for a YouTrack issue you'd need realistic use cases, and I can't think of any tbh..
y
I did have a far-fetched use case in a DSL which tracked
setValue
calls on certain special delegated variables. The way I "fixed" it was to track the child blocks that were being created, and delegate the method call to them, which is very inelegant.
🔥 1