I have these three implementations, that (should) do essentially the same: return the current position of Android exoplayer or 0 as integer.
But only nr. 1 works. Nr. 2 and nr.3 always return 0, even though player is instantiated. Is that expected behaviour?
1.
private var playbackPosition = 0
get() {
return if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
}
2.
private var playbackPosition = if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
3.
private var playbackPosition = when(player) {
null -> 0
else -> player?.currentPosition?.toInt() as Int / 1000
}
Number 1 are an implementation of a get function and invoked every time you access the variable.
Number 2 and 3 initialize a variable and the right side are only invoked once at creation time of the variable. Means the playback position is calculated only once.
The behavior works like designed. If you need the new position every time you access the variable you have to use an own getter function.
Because of the question, I assume you're not that familiar with Kotlin and/or Java, so I'm going to explain the difference between the two.
First of all, you need to understand the difference between a function and a variable/constant. A function can have a varying result when it's called (assuming it's not a void/Unit), but a variable has a fixed result until it's updated. Take this:
var toggle = Random().nextBoolean()
var dependent = if(toggle) 0 else 1
toggle = !toggle
If you print the variable before and after the toggle is switched, the variable will not change. When it's been assigned, it stays with that value until something updates it. So if you add print statements, it will be the same. Let's expand on that:
var toggle: Boolean = Random().nextBoolean()
fun someFunction() : Int = (if(toggle) 0 else 1).also { toggle = !toggle }
The also block here is an extension function that lets you do stuff, but still return the variable it's called on. Here, either 1 or 0 is returned, and the toggle is inverted. If you call this two times, you'll see a different result. This is because you get a different value based on a condition. Again, you see the value doesn't change even though the toggle does.
TL;DR: Variables have a given value until changed. Methods returning values can change based on conditions, because it's updated every time it's called.
Now, what does this mean for your code?
First of all, for the first snippet, you should use val instead. Kotlin is really nice like that; if you override the getter of a val, you don't need to initialize it. It's called backing fields.
Anyways, this:
private val playbackPosition
get() {
return if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
}
returns a value depending on the player variable when it is called. Where as the other examples:
private var playbackPosition = if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
private var playbackPosition = when(player) {
null -> 0
else -> player?.currentPosition?.toInt() as Int / 1000
}
Set the value when they're defined. You could change those to a val too; they aren't automatically re-assigned.
Initial assignment, that being the code you have there, is only run once, and that's when the class is initialized. If the variable is inside a method, the variable is initialized when the method is called. lateinit vars can be set at a later time, but initial assignment is only run once. For any changes you'll need to update it.
However, this is where methods come in handy. Depending on what you have, you could also create a backing field, a "cache" in a way. This isn't necessary unless object creation is heavy. You don't need to worry about this for something as simple as integers. Using a method that returns the value (in your case, the getter), is kinda like doing this:
var x: Int = updateValue()
fun updateValue() : Int = if ... // alternatively does x = instead of returning an int
...
x = updateValue()
x.let { foo bar }
Although that is a considerably harder way of doing stuff.
But only Nr. 1 works. Nr. 2 and Nr.3 always return 0, although player is instantiated.
If you get 0 all the time for 2 and 3, that means player == null when the variables were intiailized, but it wasn't null when the getter for the first example was called.
Is that expected behaivour?
Considering the code, yes. It's by design.
TL;DR: Again, variables aren't automatically updated when a creating condition (i.e. player == null) changes. You'll either need to manually update it, or use methods over variables.
Related
I have a kotlin class with a method
loadElements(e: Iterable<Int>) {
}
This then constructs a new copy of that Iterable as an ArrayList<Int> within the object.
It is a requirement that all the elements in that ArrayList<Int> be non-negative. It is considered a breach of contract by the caller if that is not met. I've been led to believe that "breach of contract" is something to be tested by require(), whereas check() is for testing logic internal to that method. Is this correct ?
All the examples I have seen, have the require() as the very first lines of code within the method. Is it, however, acceptable to run require() in a loop, like this ?
public fun loadElements(e: Iterable<Int>) {
elementArray.clear()
e.forEach {
require(it>=0)
elementArray.add(it)
moduleCount += it
}
if (elementCount %2 == 1)
elementArray.add(0)
check(elementCount %2 == 0)
computeInternalSizes()
}
Thing is, this means that part of the object's internals may already be set-up by the time the require() breach is detected: i.e., moduleCount will be wrong and computeInternalSizes() will never get called.
Now, of course I could just use a separate pass, with the first one checking for the require() condition, and then doing all the real work thereafter. This would mean that if the input came in as a Sequence<Int>, it would be forced to be terminal and multi-iterable.
If the require() throws, I would like to assume that the program cannot continue because a design error has occurred somewhere. However, if someone traps the resultant exception, and continues, I will end-up with an incoherent object state.
What is best practice for handling conditions where incoming parameter breaches won't be noticed until some significant unrewindable work has been done ?
I tried using a separate pass for checking for non-negativity. This worked perfectly well but, given that it could be coming from a Sequence or similar, I don't want to have to build the whole sequence, and then traverse that sequence again.
I tried using check(). This works, but it just shows up as an inconsistency in object state, rather than flagging up the incoming parameter validation, which is making a breach of contract look like an internal design fault, and just delaying the inevitable.
I've tried putting try/catch/finally all over the place, but this is an excessive amount of code for such a simple thing.
I'm not even sure if a program should attempt recovery if a require() fails.
In general you avoid situations like this, by reducing the scope of mutability in your code.
The difference between require and check is mostly a convention. They throw different Exceptions, namely IllegalArgumentException and IllegalStateException respectively. As the type of the Exceptions suggest, former is suited for validating the (user) input to a method whereas the latter is designed to check intermediate states during the runtime.
Exceptions in Kotlin should be handled as such, being an Exception that should not occur regularly. See also the Kotlin documentation why there are no checked exceptions in Kotlin.
You did not write the name of your surrounding Kotlin class, thus I'll call it Foo for the time being.
Rather than providing a function on Foo, that mutates the internal state of Foo, you could create new instances of Foo based on the Iterable<Int> / Sequence<Int>. This way, you only ever have an Foo object when its in a valid state.
private class Foo(source: Iterable<Int>) {
private val elementArray = ArrayList<Int>()
private val moduleCount: Int
init {
var internalCount = 0
for (count in source) {
require(count > 0)
elementArray.add(count)
internalCount += count
}
moduleCount = internalCount
if (elementArray.size % 2 == 1) {
elementArray.add(0)
}
check(elementArray.size % 2 == 0)
// ...
}
}
Alternatively, if you want / need to keep the interface as described in your question but also avoid the invalid state, you could make use of an intermediate copy.
As you're copying the incoming Iterable<Int> / Sequence<Int> into an ArrayList<Int> I assume you're not working with very large collections.
private class Foo(source: Iterable<Int>) {
private val elementArray = ArrayList<Int>()
private var moduleCount = 0
public fun loadElements(source: Iterable<Int>) {
val internalCopy = ArrayList<Int>()
for (count in source) {
require(count >= 0)
internalCopy.add(count)
}
elementArray.clear()
for (count in internalCopy) {
elementArray.add(count)
moduleCount += count
}
if (elementArray.size % 2 == 1) {
elementArray.add(0)
}
check(elementArray.size % 2 == 0)
// ...
}
}
I am not getting an efficient way to check below mentioned condition.
What I want to achieve is that-
There are some processes that need to be done if their corresponding boolean is true suggesting to start the process. So I want to check if a particular condition is done only if it should be started.
There are some boolean variables
var shouldStartProcessA
var shouldStartProcessB
var shouldStartProcessC
var isADone
var isBDone
var isCDone
if (shouldStartProcessA && shouldStartProcessB && shouldStartC) {
if (isADone && isBDone && isCDone) {
// Every process completed
}
}
if (shouldStartProcessA && shouldStartProcessB) {
if (isADone && isBDone) {
// Every process completed
}
}
if (shouldStartProcessA && shouldStartC) {
if (isADone && isCDone) {
// Every process completed
}
}
if (shouldStartProcessB && shouldStartC) {
if (isBDone && isCDone) {
// Every process completed
}
}
if (shouldStartProcessA) {
if (isADone) {
// Every process completed
}
}
if (shouldStartProcessB) {
if (isBDone) {
// Every process completed
}
}
if (shouldStartProcessC) {
if (isCDone) {
// Every process completed
}
}
This type of validating condition grows exponentially by introducing every other boolean. I am struggling to find a straightforward implementation to check these conditions.
Instead of doing things this way, I'd recommend a data structure that allows you to add tasks and check their state. There are a lot of ways to do that, but the basic idea is you can iterate over all the items and use functions like all to confirm they're all in the appropriate state. That way you don't have to hand-wire everything together
You could use a Map and add tasks to it, initially mapping them to false and setting that to true when they're completed. Or create a Set and add your tasks to that (I'm assuming you want one of each at most), and remove them / move them to a "done" list when they complete. That kind of idea. You could create an enum class to represent your tasks if you want, so each one is its own instance (e.g. Process.A, like having a dedicated, fixed variable) and you can easily use those in your logic
If you really want variables for each process, instead of a data structure, I'd still recommend rolling each pair into a single state, something like this:
enum class State {
UNUSED, PENDING, DONE
}
var processA = State.UNUSED
var processB = State.PENDING
// etc
// you can easily check them like this:
// create a list of all the variables you want to check - we're using references
// to the properties themselves (with the ::), not the current value!
val allProcesses = listOf(::processA, ::processB)
// now you have that collection, you can easily iterate over them all
// and work out what's what - we need to use get() to get the current values
val allFinished = allProcesses
.filterNot { it.get() == State.UNUSED } // ignore unused processes
.all { it.get() == State.DONE } // check ALL the required ones are DONE
You could write that check there as a single all condition, but the point is to show you you can be flexible with it, and build up your logic by filtering out the stuff you're not interested in, if you create a useful set of states
If you really do want to (or have to) stick with the current "pairs of variables" setup, you can do something similar:
// wiring them up again, creating a list of Pairs so we can iterate over them easily
val allProcesses = listOf(
::shouldStartProcessA to ::isADone,
::shouldStartProcessB to ::isBDone,
::shouldStartProcessC to ::isCDone
)
// gotta check 'em all - only returns true if that ALL meet the condition
val allComplete = allProcesses.all { (shouldStart, isDone) ->
// the get() syntax is awkward, but basically for everything we're checking
// if it either doesn't need to start, or it does but it's also done
!shouldStart.get() || (shouldStart.get() && isDone.get())
}
so adding new processes is just a case of adding their variables to the list of pairs, and they get included in the checking
You don't need the property reference stuff (::/.get()) if you create the lists right before you check them, but if you want to define them once in advance (and the property values can change after that) then that's how you'd do it. Otherwise you can just do the normal shouldStartProcessA to isADone etc, which is probably fine for most cases - I'm showing the reference stuff as a more general example for handling this kind of thing
I suppose, you should create two lists of Boolean and add variables consequently.
val list1 = listOf(shouldStartProcessA, shouldStartProcessB, shouldStartC)
val list2 = listOf(isADone, isBDone, isCDone)
Then iterate over both lists and check that items in corresponding positions have the same values.
var n = 0
for (i in list1.indices) {
if (list1[i] == list2[i]) {
n++
} else {
n = 0
break
}
}
if (n > 0) {
// Every process completed
}
I have an interesting situation, we have a settings database that store enum values as an int, the back end knows how to handle this but on our mobile app I'm struggle to figure how how to reproduce this.
currently I have the following:
enum class ProfileDisplayFlags(val number:Int)
{
Address(0x01),
PhoneNumber(0x02),
Email(0x04),
TwitterHandler(0x08),
GithubUsername(0x10),
Birthday(0x20)
}
for example, if I get the setting value from the database of 3, it should return on the app that I want to display Address & PhoneNumber.
I'm lost on how I can do this, I found a solution on finding a single value but I need to be able to get multiple back.
Each flag value is a different unique bit set to one, so you can filter by which ones are not masked (bitwise AND) to zero by the given flags.
companion object {
fun matchedValues(flags: Int): List<ProfileDisplayFlags> =
values().filter { it.number and flags != 0 }
}
To convert back, you can use bitwise OR on all of them.
fun Iterable<ProfileDisplayFlags>.toFlags(): Int =
fold(0) { acc, value -> acc or value.number }
I'm trying to iterate through a set to find an item. If the item is found, I want it to print a certain message and another message if item is not found. So far, it works but it print a message for each item on the set, whereas I only want one message to display: either if the item was found with the price or the message that it wasn't found. I understand this is happening because of the for loop but I'm not sure how to get it to display the not found message only once and iterate through the set all the same.
This is the code:
fun getArticleOut(code:String) {
fun onSuccess(price: Int): String {
return "Price is $price"
}
fun onError(): String {
return "Article not found"
}
for (i in house.articles) {
if (i.code.equals(code)) {
val price = calculatePrice(
articleType = i.articleType,
totalTime = i.totalTime.toInt(),
hasCard = !i.hasCard.isNullOrEmpty()
)
println(onSuccess(price))
house.articles.remove(i)
} else {
println(onError())
}
}
}
Just to clarify:
data class House(val articles: MutableSet<Articles>)
data class Articles(val code: String,
var articleType: ArticleType,
var totalTime: Calendar,
var hasCard:String?=" ")
The direct answer is the break statement, which breaks out of a for or while loop. You'd then have to move the onError() call outside the loop, with some way of telling whether the loop completed or not. For example:
var found = false
for (i in house.articles) {
if (i.code == code) {
val price = calculatePrice(
articleType = i.articleType,
totalTime = i.totalTime.toInt(),
hasCard = !i.hasCard.isNullOrEmpty())
println(onSuccess(price))
house.articles.remove(i)
found = true
break
}
}
if (!found)
println(onError())
If you don't need to do anything after both cases (as in the code in question), then you could simplify it to return, and avoid the flag:
for (i in house.articles) {
if (i.code == code) {
val price = calculatePrice(
articleType = i.articleType,
totalTime = i.totalTime.toInt(),
hasCard = !i.hasCard.isNullOrEmpty())
println(onSuccess(price))
house.articles.remove(i)
return
}
}
println(onError())
However, there are probably better approaches that don't need manual iteration. Kotlin's standard library is so powerful that any time you find yourself writing a loop, you should stop and ask whether there's a library function that would make it simpler.
In particular, you could use find(), e.g.:
val article = house.articles.find{ it.code == code }
if (article != null) {
val price = calculatePrice(
articleType = article.articleType,
totalTime = article.totalTime.toInt(),
hasCard = !article.hasCard.isNullOrEmpty())
println(onSuccess(price))
house.articles.remove(article)
} else {
println(onError())
}
That makes the code easier to read, too. (Note that the code is now saying what it's doing, not how it's doing it, which is usually an improvement.)
There are also deeper design questions worth asking, which could lead to further simplifications. For example:
If code is a unique identifier for Article, another option would be to make articles a Map from code to the corresponding Article; both checking and removal would then be constant-time operations, so more efficient as well as more concise. (Of course, that depends on how often you're doing these lookups, and what else is setting or using articles.)
Or you could override Article.equals() to check only the code. Then you could create a dummy Article with the code you're looking for, and do a simple in test (which uses the set's contains method) to check for its presence. Accessing and removing the ‘true’ one in the set would be harder, though, so that may not be a good fit.
Would be neater for calculatePrice() to be defined to take an Article directly? (Obviously that depends on whether it could be calculating the price of anything else too.) Could it even be a method or extension function on Article? (That probably depends whether the price is conceptually a property of the article itself, or whether it's specific to the getArticleOut() function and any surrounding code.)
Also worth pointing out that the code in the question has a nasty bug (which all these changes also work around), which is that it's trying to modify a collection while iterating through it, which is dangerous!
If you're lucky, you'll get an immediate ConcurrentModificationException showing you exactly what went wrong; if you're less lucky it'll continue but do something unexpected, such as skipping over an element or giving an apparently-unrelated error later on…
Which is another reason to avoid manual iteration where possible.
(The only safe way to remove an element while iterating is to manage the Iterator yourself, and use that to do the removal.)
Basically, this code works:
var optionsList = ArrayList<String>()
optionsList.add("Alpha")
optionsList.add("Bravo")
optionsList.add("Charlie")
optionsList[2] = "Foxtrot"// Assignment works (only) if initialization has been done previously through add()
However, the following makes the application crash (with no compile time errors or warnings):
var optionsList = ArrayList<String>(3)
optionsList[0] = "Alpha"
optionsList[1] = "Bravo"
optionsList[2] = "Charlie"
This seems unexpected and I can't figure out the reason for the crash. In my understanding, both ways should be equivalent - in the first we are allocating memory for and initializing only one element at a time, whereas in the second we are allocating the memory for all elements together at the beginning and later changing values.
Can someone please help me understand what might be going on under the hood here? I have only just started learning Kotlin and have used C++ in the past, so that might be affecting how I am thinking about this.
In Kotlin list[n] is a short hand for list.get(n), and with a assignment operator list[n] = value it is translated to list.set(n, value).
The optionsList[2] = "Foxtrot" tries to override the value at 2 and return the old value (that is never null) as defined in KDocs, so if there was no value at that index what will it return?
public E set(int index, E element) {
Objects.checkIndex(index, size);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
It is true that the space is allocated in the memory for the values in
var optionsList = ArrayList<String>(3)
But since operator fun set(index: Int, element: E): E requires to return the old value which is not possible because the value at that index never existed, so it fails to do the operation.
Edit: The point of allocation of space is to reduce the time taken to add a bulk of values, for instance if you wanted to add a large amount of values like 10000 then the pre-allocation (0.6ms) takes around 3.5x less time than dynamically allocated ArrayList (2ms). See: https://pl.kotl.in/iV3ZNNjOC