context functions with implicit receiver
I was playing around a bit with context functions and IMO they aren't yet as useful as they could be when it comes to the builder pattern. As a basis for discussion I take the table example from here https://dotty.epfl.ch/docs/reference/contextual/context-functions.html
Imagine I want to add a custom cell to a row, something like:
table {
row {
cell("top left")
add(new MyCell("qs")) //add is unknown
}
}
in order that I can do that I need to provide an add method which is using a Row similar to the existing cell method, basically re-publishing what is already on Row to the Context-Function world (reminds me a bit of async programming in C# where suddenly everything needs async).
def add(c: Cell)(using r: Row) = r.add(c)
IMO this boilerplate should not be necessary, it would be nice if the behaviour could be changed as follows:
- if a context function accepts exactly 1 argument, then this argument is used as implicit receiver.
thisinside such a function refers to the implicit receiver- one can use
selfor another identifier (don't know how the feature is called in scala) in the outer scope to refer to it from the context function (class A { self => ...)
But maybe it would make more sense to have a different syntax for such functions and de-sugar it to context functions behind the scene? In my opinion the syntax of Kotlin is quite nice: Row.() => Unit with the benefit that it allows to define arguments in addition which are not implicit in contrast to context functions where all arguments are implicit. For instance: Row.(Int) => Unit
I just saw that there is https://contributors.scala-lang.org/t/pre-sip-thisfunction-scope-injection-similar-to-kotlin-receiver-function but it is not active any more and without reading through the whole posts I deduce that there wasn't really a common sense. Let me know in case I should close this and continue the discussion in the aforementioned thread.