How to pass context Implicitly for constructors in Kotlin - scope

I am trying to make the construction of instances of a class depending on the scope in which they are defined without using explicit parameters.
This is part of a port from Python to Kotlin but the main idea would be something like:
var d = MyClass()
use_scope(contextAForScope) {
var a = MyClass()
use_scope(contextBForScope) {
var b=MyClass()
}
}
In this example the d constructor would use a default context, a constructor would use contextAForScope and b constructor would use contextBForScope (use_scope is just a placeholder here).
Something like implicit contexts?
Of course, I could make the constructor parameter explicit but this will potentially be used many times in a single scope and I would prefer not to define an additional variable.

class MyClass(val context: Int)
fun MyClass() = MyClass(0)
interface MyClassScope {
fun MyClass(): MyClass
}
object ContextAForScope : MyClassScope {
override fun MyClass() = MyClass(1)
}
object ContextBForScope : MyClassScope {
override fun MyClass() = MyClass(2)
}
inline fun useScope(scope: MyClassScope, block: MyClassScope.() -> Unit) {
scope.block()
}
fun main(args: Array<String>) {
val d = MyClass()
useScope(ContextAForScope) {
val a = MyClass()
useScope(ContextBForScope) {
val b = MyClass()
}
}
}
Use a factory function to create your class. If you name the function like the class, it looks like a constructor.
Define an interface with the same factory function and two objects for the scopes.
Define a function that takes the scope and the initializer block.
Now you can use the useScope-Function and within the block the right factory function is invoked.

with is what you are looking for:
class MyClass()
var d = MyClass()
fun main(args: Array<String>){
var c = "c: Could be any class"
var d = "d: Could be any class"
with(c) {
// c is "this"
var a = MyClass()
print(c) // prints "c: Could be any class"
with(d) {
// d is "this"
var b = MyClass()
}
// b is undefined in this scope
}
// a is undefined in this scope
}
with takes a lambda as argument an everything in that lambda is only defined in that scope.

Related

Kotlin anonymous object inheriting from base class but keeping derived class properties

I have a problem that I am not quire sure how to figure out elegantly:
abstract class BaseContinuousSingleObjectiveFitnessFunction {
// Invoke should compute some function, like f(x) = x^2 + 3x + 5
abstract fun invoke(x: List<Double>): Double
// This is supposed to take a function that will be called on the result of invoke
// and return an object derived from this one that has its invoke overriden to call
// the new function on the result of the original one.
fun modify(f: (Double) -> Double): BaseContinuousSingleObjectiveFitnessFunction {
val originalFunction = this
return object : BaseContinuousSingleObjectiveFitnessFunction() {
override operator fun invoke(x: List<Double>): Double = f(originalFunction(x))
}
}
}
Now, this works, but modify does not preserve the properties of the derived types.
So for example lets say I add this to the project:
class XTimesA(val a: Double): BaseContinuousSingleObjectiveFitnessFunction() {
override operator fun invoke(x: List<Double>) = x.sumByDouble { a*it }
}
Then I want to call modify on it:
val f1 = XTimesA(a = 5.0)
println(f1.a) // Works
val f2 = f1.modify { it.pow(2) }
println(f2.a) // This fails because it is not recognized as deriving XTimesA
Is there a way to not copy-paste modify into every deriving class but still keep access to the properties?
If you want to be able to access the property value on all inheritance levels, you have to lift the property up to the base class:
abstract class BaseContinuousSingleObjectiveFitnessFunction<Value>(val value: Value) {
abstract fun invoke(x: List<Value>): Value
fun modify(f: (Value) -> Value): BaseContinuousSingleObjectiveFitnessFunction<Value> {
val originalFunction = this
return object : BaseContinuousSingleObjectiveFitnessFunction<Value>() {
override operator fun invoke(x: List<Value>): Value = f(originalFunction(x))
}
}
}
Value is a generic type here for the case that Double is not applicable in all cases. If all values are of type Double than the class wouldn't need this type parameter.
You can use F-bounded polymorphism for this. Something like
abstract class BaseContinuousSingleObjectiveFitnessFunction<T : BaseContinuousSingleObjectiveFitnessFunction<T>> {
// Invoke should compute some function, like f(x) = x^2 + 3x + 5
abstract operator fun invoke(x: List<Double>): Double
abstract fun construct(f: (List<Double>) -> Double): T
// This is supposed to take a function that will be called on the result of invoke
// and return an object derived from this one that has its invoke overriden to call
// the new function on the result of the original one.
fun modify(f: (Double) -> Double): T = construct { list -> f(this(x)) }
}
open class XTimesA(val a: Double): BaseContinuousSingleObjectiveFitnessFunction<XTimesA>() {
override operator fun invoke(x: List<Double>) = x.sumByDouble { a*it }
override fun construct(f: (List<Double>) -> Double) = object : XTimesA(a) {
override operator fun invoke(x: List<Double>) = f(x)
}
}
However, in this particular case I don't think it actually makes sense and your example shows why: f1.modify { it.pow(2) } represents the function x -> x.sumByDouble { 5 * it }.pow(2) which isn't x -> x.sumByDouble { a * it } for any a!

how can i assign a closure class with a closure property

I have a class something like this
class SomeClass () {
Closure instClos
SomeClass (Closure clos) { instClos = clos} //constructor
def call() {instClos()}
}
what i'd like to be able to do is do implicit Class constructor like this
SomeClass myInst = {println "hello there}
myInst()
but that doesn't work and throws cast exception. you can make this work by writing [] round the closure to call the constructor. but its not pretty
SomeClass myInst = [{println "hello there}] // or myInst = new ({println "hello there}
myInst()
is there a nice way to create the object through assignment and have that closure stored automatically on the created class instance?
feel i'm missing some groovy syntax here that would sort this (PS i'd prefer not having to extend Closure if i can avoid that )
based on the input provided so far i provided an extended script to show the various options. I tried to add an asType closure to Closure and try and call {...} as SomeClass - but if i tried that the asType is never called so groovy must be using another mechanism when you try a coercion
class SomeClass {
Closure instClos
SomeClass (Closure clos) {
println "\tSomeClass constructor: Will constructor called"
instClos = clos
}
def call() {
println "\tSomeClass.call: calling closure "
return (instClos() + "!")
}
SomeClass asType (Closure clos) {
new SomeClass (instClos: clos)
}
}
//this will call the map constructor - needs to be explicitly provided
SomeClass me = [{println "map style construction"; "echo"}]
assert me() == "echo!"
//use new to get class instance with constructor
me = new SomeClass ({println "new SomeClass () construction"; "echo"})
assert me() == "echo!"
//using layered closure approach - doesnt read well though
def someClos = {new SomeClass(it)}
def c = someClos {println "trying layered closure ";"echo"}
assert c() == "echo!"
//extending the Closure class to add a method
ExpandoMetaClass.enableGlobally()
Closure.metaClass.some = {
if (it == SomeClass) {
new SomeClass (delegate)
}
}
//this will call .some() on closure
me = {println "hello will using .some() "; "echo"}.some ( SomeClass)
assert me() == "echo!"
I'm not aware of anyway to auto-coerce a closure. Even though groovy has closure coercion, it works by changing the closure's type, but it's still a closure, and is not layered. Some ideas:
1. Constructor
class SomeClass {
Closure instClos
SomeClass (Closure clos) { instClos = clos} //constructor
def call() {instClos() + "!"}
}
def c = new SomeClass( { "echo" } )
assert c() == "echo!"
2. Map constructor
class SomeClass {
Closure instClos
def call() {instClos() + "!"}
}
SomeClass c = [instClos: { "echo" }]
assert c() == "echo!"
3. Closure metaprogramming
(Needs enableGlobally())
ExpandoMetaClass.enableGlobally()
Closure.metaClass.some = { new SomeClass(delegate) }
def c = { "echo" }.some()
assert c() == "echo!"
4. Another closure layering
class SomeClass {
Closure instClos
SomeClass (Closure clos) { instClos = clos} //constructor
def call() {instClos() + "!"}
}
def some = { new SomeClass(it) }
def c = some { "echo" }
assert c() == "echo!"
5. Override Closure's asType
ExpandoMetaClass.enableGlobally()
def asType = Closure.metaClass.asType
Closure.metaClass.asType = { Class c ->
(c == SomeClass) ? new SomeClass(delegate) : asType(c)
}
def c = { "echo" } as SomeClass
assert c() == "echo!"
If you have enough flexibility in your design you TRULY only need one method, SomeClass.call(), then you could specify it as an interface instead:
interface SomeClass {
def call()
}
Groovy long ago anticipated the case that Java 8 formalizes with the #FunctionalInterface annotation. If you assign a Groovy Closure to variable or formal parameter of interface type, where the interface has only one method (like SomeClass as defined above), the Groovy compiler will coerce the closure into an instance of that interface. So, given the interface declaration above, the following code:
SomeClass myInst = { println "hello there" }
myInst()
prints "hello there".

Mockito ArgumentCaptor for Kotlin function

Consider a function that takes an interface implementation as an argument like this:
interface Callback {
fun done()
}
class SomeClass {
fun doSomeThing(callback: Callback) {
// do something
callback.done()
}
}
When I want to test the caller of this function, I can do something like
val captor = ArgumentCaptor.forClass(Callback::class)
Mockito.verify(someClass).doSomeThing(captor.capture())
To test what the other class does when the callback is invoked, I can then do
captor.value.done()
Question: How can I do the same if I replace the callback interface with a high order function like
fun doSomeThing(done: () -> Unit) {
// do something
done.invoke()
}
Can this be done with ArgumentCaptor and what class do I have to use in ArgumentCaptor.forClass(???)
I recommend nhaarman/mockito-kotlin: Using Mockito with Kotlin
It solves this through an inline function with a reified type parameter:
inline fun <reified T : Any> argumentCaptor() = ArgumentCaptor.forClass(T::class.java)
Source: mockito-kotlin/ArgumentCaptor.kt at a6f860461233ba92c7730dd42b0faf9ba2ce9281 ยท nhaarman/mockito-kotlin
e.g.:
val captor = argumentCaptor<() -> Unit>()
verify(someClass).doSomeThing(captor.capture())
or
val captor: () -> Unit = argumentCaptor()
verify(someClass).doSomeThing(captor.capture())
I tried what #mfulton26 suggested, but was getting an error message saying captor.capture() must not be null. and this was what worked for me.
Declared a member variable captor with #Captor annotation,
#Captor private lateinit var captor: ArgumentCaptor<Callback>
and in my #Test,
verify(someClass).doSomething(capture(captor))
I had this problem just now and solved it with an inline argumentCaptor from mockito-kotlin:
argumentCaptor<String>().apply {
verify(myClass, times(2)).setItems(capture())
assertEquals(2, allValues.size)
assertEquals("test", firstValue)
}
firstValue is a reference to the first captured object.
Source: https://github.com/mockito/mockito-kotlin/wiki/Mocking-and-verifying#argument-captors
Based on mfulton26's answer, i create an example below.
to show how to invoke the captured function or lambda expression.
you need the mockito-kotlin
Assume we have a Class A, it has a suspend function with two higher order function as parameters.
how can we mock the onSuccess scenario and onError scenario
class A {
suspend fun methodB(onSuccess: (ModelA) -> Unit, onError: (ErrorA) -> Unit)
}
Here is the dummy example
// in the unit test class
private val mockClassA = // use annotation or mock()
// decalre the higer oder function capture variables.
private val onSuccessCapture = argumentCaptor<(ModelA) -> Unit>()
private val onErrorCapture = argumentCaptor<(ErrorA) -> Unit>()
#Test
fun testMethodB = testDispatcher.runBlockingTest {
doAnswer {
// on success scenario
val modelA = // get ModelA
onSuccessCapture.firstValue.invoke(modelA) // this line will let the onSuccess parameter been called
// on error scenario
// val errorA = // get ErrorA
//onErrorCapture.firstValue.invoke(errorA)
}.`when`(mockClassA).methodB(onSuccessCapture.capture(), onErrorCapture.capture())
}

Avoid "Task not serialisable" with nested method in a class

I understand the usual "Task not serializable" issue that arises when accessing a field or a method that is out of scope of a closure.
To fix it, I usually define a local copy of these fields/methods, which avoids the need to serialize the whole class:
class MyClass(val myField: Any) {
def run() = {
val f = sc.textFile("hdfs://xxx.xxx.xxx.xxx/file.csv")
val myField = this.myField
println(f.map( _ + myField ).count)
}
}
Now, if I define a nested function in the run method, it cannot be serialized:
class MyClass() {
def run() = {
val f = sc.textFile("hdfs://xxx.xxx.xxx.xxx/file.csv")
def mapFn(line: String) = line.split(";")
val myField = this.myField
println(f.map( mapFn( _ ) ).count)
}
}
I don't understand since I thought "mapFn" would be in scope...
Even stranger, if I define mapFn to be a val instead of a def, then it works:
class MyClass() {
def run() = {
val f = sc.textFile("hdfs://xxx.xxx.xxx.xxx/file.csv")
val mapFn = (line: String) => line.split(";")
println(f.map( mapFn( _ ) ).count)
}
}
Is this related to the way Scala represents nested functions?
What's the recommended way to deal with this issue ?
Avoid nested functions?
Isn't it working in the way so that in the first case f.map(mapFN(_)) is equivalent to f.map(new Function() { override def apply(...) = mapFN(...) }) and in the second one it is just f.map(mapFN)? When you declare a method with def it is probably just a method in some anonymous class with implicit $outer reference to the enclosing class. But map requires a Function so the compiler needs to wrap it. In the wrapper you just refer to some method of that anonymous class, but not to the instance itself. If you use val, you have a direct reference to the function which you pass to the map. I'm not sure about this, just thinking out loud...

get Groovy class' closure property names

Given the following Groovy class:
class MyClass {
def someClosure = {}
def someClosure2 = {}
private privateClosure = {
}
def someVal = 'sfsdf'
String someMethod() {}
}
I need a way to retrieve the names of all public properties that have closure assigned to them, so the correct result for this class would be ['someClosure', 'someClosure2'].
I can assume that all the classes of interest have a default constructor, so if it makes things easier, I could retrieve the properties from an instance via
def instance = MyClass.newInstance()
You can simply check the value of every groovy property:
class Test {
def aClosure = {}
def notClosure = "blat"
private privateClosure = {}
}
t = new Test()
closurePropNames = t.properties.findResults { name, value ->
value instanceof Closure ? name : null
}
assert closurePropNames == ['aClosure']
The private fields are not considered groovy properties, so they won't be included in the results.

Resources