Arrow-fx has a type Atomic which is similar to java AtomicRef but with an initial value, which means I don't need to check every time while accessing the atomic value whether it's null.
Here is a simple example
import arrow.fx.coroutines.*
suspend fun main() {
val count = Atomic(0)
(0 until 20_000).parTraverse {
count.update(Int::inc)
}
println(count.get())
}
Now I would like to create a class member variable with this type, but since it's only possible to initialize within a suspend function I would like to know the possibility here.
The easiest way is to make a "fake constructor" in the companion object.
public class Thingy private constructor(
val count: Atomic<Int>
) {
companion object {
suspend fun invoke() = Thingy(Atomic(0))
}
}
Now when you write Thingy(), you're actually calling the invoke function in Thingy.Companion. For that function there are no restrictions over suspending, so you can initialize Atomic as shown above.
Related
I'm trying to access the delegate of the property (id) of a class (FooImpl). The problem is, this class implements an interface (Foo), and the property in question overrides a property of this interface. The delegate only exists in the class (not that it could exist in the interface).
The problem is that using the :: operator on a variable of type Foo always returns the property of Foo, not that of the actual instance. The problem in code:
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty0
import kotlin.reflect.jvm.isAccessible
interface Foo {
val id: Int
}
class FooImpl(
id: Int,
) : Foo {
override val id: Int by lazy { id }
}
val <T> KProperty<T>.hasDelegate: Boolean
get() = apply { isAccessible = true }.let { (it as KProperty0<T>).getDelegate() != null }
fun main() {
val foo: Foo = FooImpl(1)
println("foo::id.hasDelegate = ${foo::id.hasDelegate}")
println("(foo as FooImpl)::id.hasDelegate = ${(foo as FooImpl)::id.hasDelegate}")
}
This prints:
foo::id.hasDelegate = false
(foo as FooImpl)::id.hasDelegate = true
But this requires compile-time knowledge of the correct implementation. What I'm looking for is accessing the correct propert without having to specify FooImpl there.
The information is present at runtime because the least (!) intrusive workaround I have found so far is adding fun idProp(): KProperty0<*> to Foo and override fun idProp() = ::id to FooImpl and accessing the property using that.
Is there any better way than that?
I came up with this, but I don't know if there's a better way. The problem to work around is that getDelegate() has to return an actual instance of the delegate, so you need an instance of the class to be able to retrieve a delegate instance. It would really be nice if there was a hasDelegate property built in. Your version of hasDelegate will crash from the cast on unbound KProperty1's, which is all we have to work with when the specific class is unknown.
So to retrieve the delegate instance, we need to do search the class instance's member properties by name, which gives us a KProperty with covariant class type of the super-class type. Since it's covariant, we can call a consuming function like getDelegate() without casting to the invariant type. I think this logically should be safe, since we are passing an instance that we know has the matching type for the ::class that we retrieved the property with.
#Suppress("UNCHECKED_CAST")
fun <T: Any> KProperty1<T, *>.isDelegated(instance: T): Boolean =
(instance::class.memberProperties.first { it.name == name } as KProperty1<T, *>).run {
isAccessible = true
getDelegate(instance) != null
}
fun main() {
val foo: Foo = Foo2()
println("foo::id.hasDelegate = ${Foo::id.isDelegated(foo)}")
}
The problem here is that the owner of the property is resolved on compile time, not on runtime. When you do foo::id then foo (so FooImpl) become its bound receiver, but owner is still resolved to Foo. To fix this we wound need to "cast" property to another owner. Unfortunately, I didn't find a straightforward way to do this.
One solution I found is to use foo::class instead of foo::id as it resolves KClass on runtime, not on compile time. Then I came up with almost exactly the same code as #Tenfour04.
But if you don't mind using Kotlin internals that are public and not protected with any annotation, you can use much cleaner solution:
val KProperty0<*>.hasDelegate: Boolean
get() = apply { isAccessible = true }.getDelegate() != null
fun KProperty0<*>.castToRuntimeType(): KProperty0<*> {
require(this is PropertyReference0)
return PropertyReference0Impl(boundReceiver, boundReceiver::class.java, name, signature, 0)
}
fun main() {
val foo: Foo = FooImpl(1)
println(foo::id.castToRuntimeType().hasDelegate) // true
}
We basically create a new instance of KProperty, copying all its data, but changing the owner to the same type as its bound receiver. As a result, we "cast" it to the runtime type. This is much simpler and it is also cleaner because we separated property casting and checking for a delegate.
Unfortunately, I think Kotlin reflection API is still missing a lot of features. There should be hasDelegate() function, so we don't have to provide receivers, which is not really needed to check if property is delegated. It should be possible to cast KProperty to another type. It should be possible to create bound properties with some API call. But first of all, it should be possible to do something like: Foo::id(foo), so create KProperty of the runtime type of foo. And so on.
I have a code that looks like the following:
infix fun <T> Option<T>.valueIs(value : T): Pair<() -> Boolean,Set<Node>> {
val function = {this.selectedValue == value}
val parents = setOf(this)
return Pair(function, parents)
}
My question is if Kotlin will always create an anonymous object in val function = {this.selectedValue == value} in the JVM every time that this extension function is called or if it has some sort of optimization to reuse it if this and value are the same.
Kotlin, like Java, can avoid creating a new object each time if your lambda doesn't access (also called "capture") variables declared outside it (including this); {this.selectedValue == value} captures this and value, so it doesn't.
You could imagine some cache mapping captured variables to lambda instances, so it's effectively
private val lambdas = mutableMapOf<Any, () -> Boolean>()
infix fun <T> Option<T>.valueIs(value : T): Pair<() -> Boolean,Set<Node>> {
val function = lambdas.getOrUpdate(Pair(this, value)) {this.selectedValue == value}
val parents = setOf(this)
return Pair(function, parents)
}
but:
it prevents lambdas from being garbage-collected just in case you'll call the method with the same this and value later (could be fixed by using WeakHashMap);
it's non-trivial overhead even neglecting that;
it requires any captured values to have well-behaved hashCode and equals. Ok, they should have them anyway, but just imagine problems from debugging this if they don't!
Kotlin has another very important way to avoid creating objects for lambdas: passing them as arguments to inline functions. Of course it isn't applicable when you want to put your lambda into a data structure (even one as simple as Pair) or just return it.
Decompiling the bytecode:
#NotNull
public static final Pair valueIs(#NotNull final Option $this$valueIs, final Object value) {
Intrinsics.checkParameterIsNotNull($this$valueIs, "$this$valueIs");
Function0 function = (Function0)(new Function0() {
// $FF: synthetic method
// $FF: bridge method
public Object invoke() {
return this.invoke();
}
public final boolean invoke() {
return Intrinsics.areEqual($this$valueIs.getSelectedValue(), value);
}
});
Set parents = SetsKt.setOf($this$valueIs);
return new Pair(function, parents);
}
As we can see, the lambda creates a new object Function0 every time this function is called.
So, every time this function is called. It seems that a new object will be created.
I thought typealiases were the same as the original type, just a different name.
I figure typealiases have the same references as the original type.
typealias Celsius = Double
fun Double.Companion.foo() {} // Works
fun Celsius.Companion.foo() {} // Does not work
Here, Companion is accessible from Double but Celsius gives an unresolved reference error.
No, you can't access to the companion objects via typealias. One possible workaround to create one more typealias for concrete companion:
typealias CelsiusCompanion = Double.Companion
After that you can use it as following:
fun CelsiusCompanion.foo() {}
If you want to define an extension function, it is not possible as hluhovskyi already stated, but things are differently if you just want to invoke functions of a companion object.
There are two ways of accessing functions and properties within a companion object. You can either specify the access explicitely or implicitely. The implicit way works with a typealias the explicit one does not.
Consider this minimal example:
class ClassWithCompanion{
companion object {
fun sayHello() {
println("Hello")
}
}
}
typealias Alias = ClassWithCompanion
fun main(args: Array<String>) {
ClassWithCompanion.sayHello() // implicit
ClassWithCompanion.Companion.sayHello() // explicit
Alias.sayHello() // implicit (works)
Alias.Companion.test() // explicit (does not work)
}
A previous question shows how to put a static initializer inside a class using its companion object. I'm trying to find a way to add a static initializer at the package level, but it seems packages have no companion object.
// compiler error: Modifier 'companion' is not applicable inside 'file'
companion object { init { println("Loaded!") } }
fun main(args: Array<String>) { println("run!") }
I've tried other variations that might've made sense (init on its own, static), and I know as a workaround I can use a throwaway val as in
val static_init = {
println("ugly workaround")
}()
but is there a clean, official way to achieve the same result?
Edit: As #mfulton26's answer mentions, there is no such thing as a package-level function really in the JVM. Behind the scenes, the kotlin compiler is wrapping any free functions, including main in a class. I'm trying to add a static initializer to that class -- the class being generated by kotlin for the free functions declared in the file.
Currently there is no way to add code to the static constructor generated for Kotlin file classes, only top-level property initializers are getting there. This sounds like a feature request, so now there is an issue to track this: KT-13486 Package-level 'init' blocks
Another workaround is to place initialization in top-level private/internal object and reference that object in those functions that depend on the effect of that initialization. Objects are initialized lazily, when they are referenced first time.
fun dependsOnState(arg: Int) = State.run {
arg + value
}
private object State {
val value: Int
init {
value = 42
println("State was initialized")
}
}
As you mentioned, you need a property with something that would run on initialisation:
val x = run {
println("The package class has loaded")
}
I got around it by using a Backing Property on the top-level, under the Kotlin file. Kotlin Docs: Backing Properties
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
get() {
if (_table == null) {
_table = HashMap() // Type parameters are inferred
// .... some other initialising code here
}
return _table ?: throw AssertionError("Set to null by another thread")
}
In a method I would like to receive KMutableProperty as parameter and assign a value to it.
Another question is what is the correct way of passing a parameter into such a method.
Basically I would like to have something like that:
class MyBinder {
...
fun bind(property: KMutableProperty<Int>): Unit {
property.set(internalIntValue)
}
}
And then call it in another class
myBinder.bind(this::intProperty)
Kotlin 1.0 does not allow the this::intProperty syntax, but this is being worked currently and will be available soon as a part of the early access preview of 1.1 (issue, KEEP proposal).
With this in mind, I'd consider doing what you're describing in another way, for example making bind accept a lambda which sets the property:
class MyBinder {
fun bind(setProperty: (Int) -> Unit) {
setProperty(internalIntValue)
}
}
...
myBinder.bind { intProperty = it }
Anyway, to answer your question about setting the value of KMutableProperty: to set the value of some property or, technically speaking, to invoke the property setter, you should know its arity, or the number of parameters that property (and its getter/setter) accepts. Properties declared in a file do not accept any parameters, member properties and extension properties require one parameter (the receiver instance), while member properties which are also extensions take two parameters. These kinds of properties are represented by the following subtypes of KMutableProperty respectively: KMutableProperty0, KMutableProperty1, KMutableProperty2 -- the number means the arity and their generic type parameters mean the types of receivers. Each of these property types has a set method with the corresponding parameters. Some examples:
fun setValue(property: KMutableProperty0<Int>, value: Int) {
property.set(value)
}
fun setValue(property: KMutableProperty1<SomeType, Int>, instance: SomeType, value: Int) {
property.set(instance, value)
}
Note that there's no set (or get) method in the abstract KMutableProperty interface precisely because it's impossible to declare it, not knowing the number of required receiver parameters.
Additionally to Alexander's answer, you can try something like this:
import kotlin.reflect.KMutableProperty
class Binder {
val internalIntValue = 10
fun bind(self: Any, aProperty: KMutableProperty<Int>) {
aProperty.setter.call(self, internalIntValue)
}
}
class Foo {
var bar = 1
fun changeBar() {
Binder().bind(this, Foo::bar)
}
}
fun main(args: Array<String>) {
val foo = Foo()
assert(1 == foo.bar)
foo.changeBar()
assert(10 == foo.bar)
}
A more robust/safe way to do the same thing:
fun <T> bind(self: T, aProperty: KMutableProperty1<T, Int>) {
aProperty.set(self, internalIntValue)
}
My thanks to Alexander. His answer gave me the previous idea.