Given something that implements Iterable<*>.
Most implementations return an iterator that iterates >1 values.
I'm creating a specific implementation that returns an iterator that iterates 1 value.
What is the best implementation?
Given the implementation implements Iterable<Any>, and has a property named value of type Any:
override fun iterator(): Iterator<Any> = iterator {
return#iterator this.yield(this#ExampleIterable.value)
}
Is this the most efficient (albeit, not most concise) implementation of a single-element iterator?
That is far from the most efficient implementation on the JVM, if you are not considering conciseness. The following, for example, would be more efficient:
override fun iterator() = object: Iterator<Expression> {
var nextCalled = false
override fun hasNext() = !nextCalled
override fun next(): Expression {
if (nextCalled) {
throw NoSuchElementException()
}
nextCalled = true
return value
}
}
or as an inline function:
inline fun <T> iteratorOfOne(crossinline elem: () -> T) = object: Iterator<T> {
var nextCalled = false
override fun hasNext() = !nextCalled
override fun next(): T {
if (nextCalled) {
throw NoSuchElementException()
}
nextCalled = true
return elem()
}
}
For one, this doesn't use coroutines like the iterator function does, so it avoids a lot of the overhead that coroutines create. For something as simple as an iterator returning a single element, the overhead of coroutines could be quite a lot.
Looking at the bytecode, you can see that it first instantiates the inner class that represents the lambda return#iterator this.yield(this#ExampleIterable.value), and then calls SequencesKt.iterator.
The lambda inner class actually implements state machine-like thing, kind of like what I did with nextCalled, but with an Int instead, and some added coroutine overhead.
For example, iterator { yield(Any()) } produces the following invokeSuspend implementation in the inner class (decompiled to Java):
int label;
#Nullable
public final Object invokeSuspend(#NotNull final Object $result) {
final Object coroutine_SUSPENDED = IntrinsicsKt.getCOROUTINE_SUSPENDED();
switch (this.label) {
case 0: {
ResultKt.throwOnFailure($result);
final SequenceScope sequenceScope;
final SequenceScope $this$iterator = sequenceScope = (SequenceScope)this.L$0;
final Object o = new Object();
final Continuation continuation = (Continuation)this;
this.label = 1;
if (sequenceScope.yield(o, continuation) == coroutine_SUSPENDED) {
return coroutine_SUSPENDED;
}
break;
}
case 1: {
ResultKt.throwOnFailure($result);
break;
}
default: {
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
}
return Unit.INSTANCE;
}
Then iterator makes an Iterator implementation out of that coroutine. The source code looks like this:
public fun <T> iterator(#BuilderInference block: suspend SequenceScope<T>.() -> Unit): Iterator<T> {
val iterator = SequenceBuilderIterator<T>()
iterator.nextStep = block.createCoroutineUnintercepted(receiver = iterator, completion = iterator)
return iterator
}
Again, more stuff that doesn't actually need to happen, if you've just created and returned an instance of Iterator<T> yourself.
The point is, there is a lot of overhead with creating a whole coroutine just to make a single-element iterator. In the grand scheme of things, this might not matter - you probably have other code that does way more work than this - but if we are just comparing these things in a vacuum, then creating an anonymous class is faster.
Related
Context:
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
data class DatabaseData(
val a: String,
val b: String
)
interface DatabaseFetcher {
suspend fun get(): DatabaseData
}
class MyClass(
private val databaseFetcher: DatabaseFetcher
) {
suspend fun a() = coroutineScope {
val a = async { databaseFetcher.get().a }
//imagine more async{}'s here
a //imagine a gets computed in regards to the other async{}'s as well
}
suspend fun b() = databaseFetcher.get().b
}
class MyController(private val databaseFetcher: DatabaseFetcher) {
suspend fun someFun() = coroutineScope {
// the reduced example doesn't need a coroutineScope of course, imagine some async{} here
MyClass(databaseFetcher)
}
}
I am trying to call databaseFetcher.get() only once if either a() or b() are called on MyClass. Basically a lazy future that gets started when either a() or b() is called, but with coroutines.
What I have tried so far:
Can't use by lazy{} as the coroutineScope matters here and I can't use withContext(Dispatchers.IO) as I use a custom Context (multithreading, Spring request scoped data etc.) - passing my context in here seems awkward (would it be bad practice?)
I can't pass an async(start = CoroutineStart.LAZY) when constructing MyClass as it would block indefinitely if the Deferred<T> is never await()ed on, which may happen when neither a() or b() is called. It also blocks indefinitely because the corresponding coroutineScope is constructed when MyClass is constructed which would block as a() and b() are called later after MyClass has been fully constructed because (as I understand) a coroutineScope is only unblocked when all its children are done, which doesn't hold true for a lazy async thats awaited outside the curent scope
Using a wider coroutine context may leak when the lazy async is never awaited - is this true? I couldn't find much about this
This is being done in the context of GraphQL wherein either a b or both can be selected. There are boilerplatey solutions to this but as I am still learning about coroutines I wondered if there is an elegant solution to this which I don't see yet. The CoroutineStart.LAZY issue really caught me by surprise :)
I have found a solution for this:
fun <T : () -> U, U> T.memoized(): suspend () -> Deferred<U> {
val self = this
val deferred: CompletableDeferred<U> = CompletableDeferred()
val started = AtomicBoolean(false)
return suspend {
if (started.compareAndExchange(false, true)) {
deferred
} else {
coroutineScope {
async {
deferred.complete(self())
deferred.await()
}
}
}
}
}
Any () -> T function (basically any function with captured arguments) can be .memoized(). Whatever callee first calls the returned suspend fun will be used to start the Deferred<U> while allowing said callee to block whenever he sees fit:
val expensive = { someExpensiveFun(param, param2 }.memoize();
withContext(Dispatchers.IO) { // or some other context
val a = expensive()
val b = expensive()
a.await()
b.await()
}
I'm trying to understand the functional programming paradigm so I'm playing around with an immutable linked list. I've created a Bag with some utility functions and now I want to iterate through the collection. I want to implement an Iterable:
sealed class Bag<out A> : Iterable<A> {
companion object {
fun <A> of(vararg aa: A): Bag<A> {
val tail = aa.sliceArray(1 until aa.size)
return if (aa.isEmpty()) Nil else Cons(aa[0], of(*tail))
}
/**
* Returns the tail of the bag
*/
fun <A> tail(bag: Bag<A>): Bag<A> =
when (bag) {
is Cons -> bag.tail
is Nil -> throw IllegalArgumentException("Nil cannot have a tail")
}
/**
* Add an item to the beginning
*/
fun <A> add(bag: Bag<A>, elem: A): Bag<A> =
Cons(elem, bag)
fun <A> isEmpty(bag: Bag<A>): Boolean =
when (bag) {
is Nil -> true
is Cons -> false
}
}
class BagIterator<A> : Iterator<A> {
override fun hasNext(): Boolean {
TODO("Not yet implemented")
}
override fun next(): A {
TODO("Not yet implemented")
}
}
}
object Nil : Bag<Nothing>() {
override fun iterator(): Iterator<Nothing> =
BagIterator()
}
data class Cons<out A>(val head: A, val tail: Bag<A>) : Bag<A>() {
override fun iterator(): Iterator<A> =
BagIterator()
}
Now I'm stuck with hasNext() and next() implementations. I'm not even sure if this approach works. Can I implement Iterable this way?
Note that an Iterator is a mutable thing. next must mutate the iterator's current state. Its signature does not allow you to "return a new Iterator with a different state". So if you wanted to do that, sad news for you :( This is because the way that iteration is supposed to happen is (this is roughly what a for loop translates to):
val iterator = something.iterator()
while (iterator.hasNext()) {
val elem = iterator.next()
...
}
Now knowing that, we can store a var current: Bag<A>:
// in Bag<A>
class BagIterator<A>(var current: Bag<A>) : Iterator<A> {
override fun hasNext(): Boolean = current !is Nil
override fun next(): A {
val curr = current
return when (curr) {
is Nil -> throw NoSuchElementException()
is Cons -> curr.also {
current = it.tail
}.head
}
}
}
override fun iterator(): Iterator<A> = BagIterator(this)
And the Nil and Cons types can have empty bodies.
If you don't like this, blame the standard library designers :) You can always write your own Iterator<A> interface, but of course you can't use the for loop with your Bag if you do that. You can write your own forEach extension function though.
Looking for a natural Kotlin way to let startTime be initialized only in a particular place and exactly once.
The following naive implementation have two problems:
it is not thread safe
it does not express the fact "the variable was or will be assigned exactly once in the lifetime of an Item instance"
class Item {
var startTime: Instant?
fun start(){
if (startTime == null){
startTime = Instant.now()
}
// do stuff
}
}
I believe some kind of a delegate could be applicable here. In other words this code needs something similar to a lazy variable, but without initialization on first read, instead it happens only after explicit call of "touching" method. Maybe the Wrap calls could give an idea of possible implementation.
class Wrap<T>(
supp: () -> T
){
private var value: T? = null
private val lock = ReentrantLock()
fun get(){
return value
}
fun touch(){
lock.lock()
try{
if (value == null){
value = supp()
} else {
throw IllegalStateExecption("Duplicate init")
}
} finally{
lock.unlock()
}
}
}
How about combining AtomicReference.compareAndSet with a custom backing field?
You can use a private setter and make sure that the only place the class sets the value is from the start() method.
class Item(val value: Int) {
private val _startTime = AtomicReference(Instant.EPOCH)
var startTime: Instant?
get() = _startTime.get().takeIf { it != Instant.EPOCH }
private set(value) = check(_startTime.compareAndSet(Instant.EPOCH, value)) { "Duplicate set" }
fun start() {
startTime = Instant.now()
}
override fun toString() = "$value: $startTime"
}
fun main() = runBlocking {
val item1 = Item(1)
val item2 = Item(2)
println(Instant.now())
launch { println(item1); item1.start(); println(item1) }
launch { println(item1) }
delay(1000)
println(item2)
item2.start()
println(item2)
println(item2)
item2.start()
}
Example output:
2021-07-14T08:20:27.546821Z
1: null
1: 2021-07-14T08:20:27.607365Z
1: 2021-07-14T08:20:27.607365Z
2: null
2: 2021-07-14T08:20:28.584114Z
2: 2021-07-14T08:20:28.584114Z
Exception in thread "main" java.lang.IllegalStateException: Duplicate set
I think your Wrap class is a good starting point to implement this. I would definitely make it a property delegate and touch() could be much simplified:
fun touch() {
synchronized(this) {
check(value == null) { "Duplicate init" }
value = supp()
}
}
Then you can remove lock. But generally, this is a good approach.
If you would like to reuse lazy util from stdlib then you can do this by wrapping it with another object which does not read its value until asked:
class ManualLazy<T : Any>(private val lazy: Lazy<T>) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T? {
return if (lazy.isInitialized()) lazy.value else null
}
fun touch() {
lazy.value
}
}
class Item {
private val _startTime = ManualLazy(lazy { Instant.now() })
val startTime: Instant? by _startTime
fun start(){
_startTime.touch()
}
}
Of course, depending on your needs you can implement it in a much different way, using a similar technique.
This may be considered exploiting or hacking lazy util. I agree and I think Wrap approach is a better one.
I have a function that catches recoverable exceptions and returns a fallback
private fun <T> safely(block: () -> T, fallback: T): T {
return try {
block()
} catch(exc: SomeException) {
// Log the exception/do some logic
fallback
}
}
I want to be able to add this to the public methods of my class e.g.
fun doSomething(): List<String> = safely({
val list = mutableListOf<String>("Hello")
fun someCheck1() = false // Some boolean value
fun someCheck2() = true // Some boolean value
do {
if(someCheck2()) {
return arrayListOf<String>("Hello", "World")
}
} while (someCheck1())
return list
}, arrayListOf<String>())
However I get compiler errors 'return' is not allowed here
Yet if I remove the return then my return in the loop no longer works and it gets highlighted in my IDE with warning the expression is never used
How can I maintain this type of return logic within a Lambda?
Playground Example
Try
fun doSomething(): List<String> = safely(
{
val list = mutableListOf<String>("Hello")
fun someCheck1() = false // Some boolean value
fun someCheck2() = true // Some boolean value
do {
if (someCheck2()) {
return#safely arrayListOf<String>("Hello", "World")
}
} while (someCheck1())
list
}
, arrayListOf<String>())
For further reference, check Using return inside a lambda?
Or you can also extract your block into a separate function (i.e. someCheckFunction(): List<String>), and have fun doSomething() = safely({ someCheckFunction() }, arrayListOf()), but I guess you want to maintain lambda code like above.
return arrayListOf<String>("Hello", "World") here tries to return a value from doSomething function rather than from the lambda passed to safely. However, such return is non-local, since it tries to exit from the function that is not on the top of stack, and therefore it is prohibited.
Another option here is to make safely function inline:
inline fun <T> safely(block: () -> T, fallback: T): T { ... }
and then you'll be able to make a non-local return from block lambda function passed to it.
We can do
val obj = Obj()
with (obj) {
objMethod1()
objMethod2()
}
But is there a way to do this?
val obj = with(Obj()) {
objMethod1()
objMethod2()
}
To solve a common case where you create an object and call a few methods on it to initialise its state.
Sure, you can use the .apply { } stdlib function, which
Calls the specified function block with this value as its receiver and returns this value.
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
Usage example:
val obj = Obj().apply {
objMethod1()
objMethod2()
}
You can find it among many other Kotlin idioms here in the reference.
Your second example works too - just make sure that the lambda returns the correct value (the result of the last expression is the returned value of the with expression):
val obj = with(Obj()) {
objMethod1()
objMethod2()
this // return 'this' because we want to assign the new instance to obj
}