I guess withContext has to be a function which get a lambda function as param, but the concrete impl...
j
I guess withContext has to be a function which get a lambda function as param, but the concrete implementation is not clear
l
fun withContext(block: (Context) -> Unit){}
j
Yes, so far I got that too
l
and you can call
block()
inside to execute
with the context argument of course
j
you mean call the block method?
l
Well I assume you want to execute whatever is inside so yes,
block(context)
j
but where does the context comming from?
l
don't you have a context instance variable?
do you want to pass a context to the method as well?
I think I don't quite understand what you are trying to do
j
so in my original code I've created a new Service with he `createServiceFoo`method based on the context
the ServiceFoo needs an enhanced baseClient
to enhance the baseClient I need the context
based on the context I can create a new baseClient which I can base to the ServiceFoo and use it there
just check my original code
l
ah ok I see now
k
So you want both a context and a client available in the lambda?
Where you're able to implicitly call things on the context?
j
I need the context to be able to create an instance of ServoceFoo
l
you'll have to save the context in ServiceFoo then
j
my Factory class has one public method which gets the context, adds it to his private baseClient (it creates a mutation of the baseClient) and the mutated baseClient can be used in my Service
the Service does not no anything about the context, he just gets a client as a constructor parameter and uses it
l
but you need that context to call the block in withContext
k
Something like this:
Copy code
class ServiceFooFactory {
	...
	fun createWithContext(context: Context, block: ServiceFoo.() -> Unit): ServiceFoo {
		val service = createServiceFoo(context)
		service.block()
		return service
	}
}
Called like
val service = factory.createWithContext(context) { hello("Bar") }
l
do you have access to the context from baseClient?
j
@karelpeeters yes!!!
but in scala you can do sg like
factory.createWithContext {context -> hello("Bar") }
can't we have the context in the same closure?
l
fun withContext(block: (Context) -> Unit){block(baseClient.context)}
?
j
ohh that was your quest
the context is comming from outside
and it has to be added to the baseClient
it actually looks like this:
Copy code
fun someFun(callParam, context) {
    factory.createServiceFoo(context).hello(callParam)
}
based on @karelpeeters's idea I can do now this:
Copy code
fun someFun(callParam, context) {
    factory.createWithContext(context) {
        hello(callParam)
    }
}
which is a nice step forward
and my end goal is this:
Copy code
fun someFun(callParam, context) {
    factory.createWithContext { context ->
        hello(callParam)
    }
}
k
I don't really see how that's different from what I did, do you just want a different syntax for "passing
context
as a parameter"?
j
yes!
just for the sake of syntax sugar
technically your solution already does what it has to do
k
Isn't that really confusing?
j
do you think?
I think frameworks like Play are doing this all the time
Anyways thanks a lot!
for both of you
oh shit... 😞
the withContext cannot return with value of the hello() function
k
It should work, any value for the last line is okay for a Unit-returning function normally.
And I think it's confusing because you're conflating parameters with _ arguments_.
context
in
{ context -> ... }
is normally a parameter, but you want it it be a value, ie. an argument..
j
I have cheated a little bit and checked the Kotlin's with function
based on that this is what I did:
Copy code
fun <R> with(context: Context, block: Api.() -> R): R {
        val service = Api(baseClinet.addHeader(context))
        return service.block()
    }
val retVal: String = serviceFoo.with(HttpContext) { hello("WithContext")  }
this is what I can do now 🙂
and the retVal's type will be always the return type of the method call inside the closure
k
Ah isn't it good enough to hardcode that it returns the service?
j
nope in the higher function I have to return with the service function's return object
k
I see.
j
So
This is what I've ended up with:
Copy code
class ServiceFoo {
    private val baseClient = Client()
    

    internal fun <R> with(context: Context, block: Api.() -> R): R {
        val service = Api(baseClient.addHeader(context))
        return service.block()
    }

    internal class Api(private val enhancedClient: Client) {
        fun hello(name: String): String {
            enhancedClient.getMethod(name)
            return name
        }


        fun hello2(name: String): Int {
            enhancedClient.getMethod(name)
            return 2
        }
    }
}

fun main(args: Array<String>) {
    val serviceFoo = ServiceFoo()


    val retVal: Int = serviceFoo.with(HttpContext) {
        hello2("WithContext")
    }
}
What do you think? Do you like the naming or should I leave the wrapper class as
ServiceFooFactory
and the
Api
as
ServiceFoo
Check this:
internal fun <R> with(context: Context, block: Api.() -> R): R = Api(baseClient.addHeader(context)).run(block)
I've transformed it to a one liner! 🙂
@karelpeeters thanks a lot! I really like what we did here 🙂
k
Nice one liner! Glad I could be of some help even with my choppy internet.
Naming you'll have to decide for yourself as I don't have the full context (heh) here simple smile