I came across this
private final Function1<byte[], Boolean> successConditionForResponse;
and wonder how to compare two of this in Java or Kotlin?
I search but cant really find specifically
Well, what do you want this comparison to do? equals on functions will check whether they are the same object, because it doesn't override the default implementation (so will ==, but you don't want to get into habit of using it for objects in Java). So if that's what you want, you are done.
If you want to check that two functions are equal semantically (that is, they give the same result and have the same side effects when invoked on any arguments), there's no way to do it and there really can't be for well-known mathematical reasons.
Finally, you may want to know whether they are created by the same lambda and capture the same values. This should be possible to do for Kotlin lambdas by serializing them and comparing results, for Java lambdas you need to create them in a specific way. This is kind of a hack and slow, but may be good enough.
Case 1.
Let's say you have:
val a: (ByteArray) -> Boolean = ...
val b: (ByteArray) -> Boolean = ...
In this case you have two Kotlin functions assigned to two vals.
If you want to compare the results of the two functions on a given argument, you can do:
if(a(someByteArray) == b(someByteArray))
Instead, if you truly want to compare the two functions, you can simply do:
if(a == b)
Case 2.
Let's say you have:
val a: Function1<ByteArray, Boolean> = ...
val b: Function1<ByteArray, Boolean> = ...
In this case you don't have two Kotlin functions, but two objects of type Function1<T, R>.
Similarly to the previous case:
Comparing the results of the functions:
if (a.apply(someByteArray) == b.apply(someByteArray))
Comparing the two objects of type Function1<ByteArray, Boolean>:
if(a == b)
Related
This might be a very silly question, but I am logging the methods that are triggered in my app as strings. When an issue is submitted, I would like to automatically input the text of the strings as parameters for methods. E.g:
For method:
fun assignPot(potType: PotType, ball: DomainBall, action: PotAction) {...}
I'd like to somehow call method:
assignPot(FOUL(2, BLUE(5), SWITCH))
From String:
"FOUL(2, BLUE(5), SWITCH)"
The only workaround I can think of is to split the string and create a when -> then function to get actual classes from strings, but I wondered if there's a more concise way for this.
This is not what you want to do. You should design your app in a way that prevents users from providing input similar to actual code.
However, you can achieve this. Complex parsings like this oftenly use regex-based approaches.
As you said, you should map your string part to class. If your PotType is enum, you can do something like
val re = Regex("[^A-Za-z\s]")
val reNumbers = Regex("[^0-9\s]")
// get classes
val classNames = originalString.replace(re, "").split(" ")
// get their constructor numerical arguments
val classArgs = originalString.replace(reNumbers, "").split(" ")
After that you can implement mapping with when expression. You probably will use some collection of Any type.
As you see, this sadly leads you to parsing code by code. Concise way to solve is to implement your own script compiler/interpreter and use it in your application :) That will later lead you to dealing with security breaches and so on.
If you are logging problematic method calls and want to repeat them immediately after issue is submitted, you probably want to programatically save the calls to lambdas and call them when you receive an issue log.
Let val a, b, x, y: LocalDate.
Then a..b in x..y is no valid expression: ClosedRange in ClosedRange is undefined.
However, (a..b).toRange() in (x..y).toRange() does work since Range in Range is defined.
Except when b < a or y < x since ranges can't be negative.
Please note that i'm developing for Android, which is where the .toRange() originates: androidx.core/core-ktx
3 Questions arise
Is this an oversight of the android / kotlin team?
Is this a deliberate decision? (e.g. because of some unintuitive behavior)
in case it's a deliberate decision: how to best circumvent it?
ClosedRange is part of the Kotlin standard library. Range is part of Android's SDK. These two libraries are made by different companies and were made with different goals in mind, so you can't necessarily call it an oversight. Maybe the Kotlin developers decided the meaning of a range being in another range might be ambiguous, and the Android developers didn't. Or maybe the Kotlin developers have a higher criteria for what functions are useful enough to include in the standard library.
One difference between the two classes is that the Android Range class forbids a range with the start value higher than the lower, but Kotlin ClosedRange allows it. This makes the concept of a ClosedRange containing another more ambiguous than with Ranges. What would it mean for a negative-direction ClosedRange to be in another ClosedRange? It's empty, but it has a span.
I'm not sure what you mean by circumventing it. You can define your own extension function for ClosedRange if you want, with behavior that depends on how you want to interpret the meaning of an empty range being contained.
operator fun <T: Comparable<T>> ClosedRange<in T>.contains(other: ClosedRange<out T>): Boolean =
other.start in this && other.endInclusive in this
// or
operator fun <T: Comparable<T>> ClosedRange<in T>.contains(other: ClosedRange<out T>): Boolean =
other.isEmpty() || (other.start in this && other.endInclusive in this)
// or
operator fun <T: Comparable<T>> ClosedRange<in T>.contains(other: ClosedRange<out T>): Boolean =
(other.isEmpty() && (other.start in this || other.endInclusive in this)) ||
(other.start in this && other.endInclusive in this)
Disclaimer: I'm not an Android developer and have no experience with androidx.core, so take my answer with a pinch of salt.
So assuming that you can do a..b to create a ClosedRange (which is something not available by default in the Kotlin stdlib, but maybe core-ktx defines its own extension for that), according to the Kotlin documentation, x in y gets translated to y.contains(x). Now, ClosedRange defines some contains methods, but none of them accepts another ClosedRange as a parameter, hence your error.
Now, apparently the Android stdlib defines its own concept of Range, which is unrelated to Kotlin's ClosedRange (as one does not extend the other). However, core-ktx defines a function to transform a ClosedRange to a Range, and that function is .toRange(). In addition to that, Range defines a contains(Range) method, hence why the second example compiles correctly.
So to summarise: Kotlin doesn't allow (1) to create ranges of dates by default, and (2) to check if one range is fully included in another range. However, you can easily overcome (1) by creating your own function to create a ClosedRange for dates (by creating a rangeTo extension function), and (2) by creating your own contains(Range) function.
Coming back to why a..b works when using core-ktx, I can't find a satisfactory answer. That library contains a rangeTo extension function to create a range out of any Comparable (and LocalDate is-a Comparable), but that function returns a Range, not a ClosedRange, so I'm not sure why a..b in x..y doesn't work in the first place.
I recently found myself writing the following code:
fun listener() {
// Do some stuff
adapter.removeLoadStateListener(::listener)
}
adapter.addLoadStateListener(::listener)
A colleague remarked on the fact that
val x1 = ::listener
val x2 = ::listener
x1 == x2 //true
x1 === x2 //false
However,
var mySet = mutableSetOf<() -> Unit>()
fun a() { }
fun b() { }
mySet.add(::a)
mySet.add(::b)
mySet.remove(::a)
mySet.contains(::a) // false
mySet.contains(::b) // true
Based on this I get the impression I do not understand ::myFun properly and I start to question if my original code is safe to use.
TL;DR
Is it safe to use ::listener to reference a method to be used as a listener and that will need to be referenced multiple times (e.g. add + remove)?
What is actually going on behind the scenes regarding anonymous classes etc.?
EDIT
Eventually we decided against using ::listener for this case. However, we ran into a new problem since add/removeLoadStateListener will only accept the (CombinedLoadState) -> Unit type.
I'll leave our solution to that problem here for future reference and other readers as it is related (I expect some may even come here looking for this rather than answers to the original question):
val listener = object : (CombinedLoadStates) -> Unit {
override operator fun invoke(loadState: CombinedLoadStates) {
// Do some stuff
adapter.removeLoadStateListener(this)
}
}
adapter.addLoadStateListener(listener)
When you use ::listener, you are sort of creating an anonymous class that implements the interface, each time. However, as your test shows, the .equals of the anonymous classes will return that they are equal, which usually wouldn't be the case with an anonymous class (created with object: syntax). So, two instances created using ::listener will be equivalent with == but not with ===.
Sets typically use .equals equality (==) to determine if an instance is a duplicate, but it's possible to create a Set backed by IdentityHashMap so it effectively behaves as a Set using identity comparison. This breaks the Set contract, but a class could be using it internally for some reason.
Whether it is safe to use this depends on whether the class you're working with compares listener instances by .equals or identity. If it's possible it's using an IdentityHashMap to store and compare listeners, then this is not safe.
I am new to Kotlin (coming from Delphi, which is object-oriented Pascal). I just want to ensure I am having functions return List<>s correctly:
Making up an absurdly simple example here:
fun firstTenInts(): List<Int> {
val iList: MutableList<Int> = mutableListOf()
for (i in 1..10)
iList.add(i)
return iList
}
So, my thoughts/questions here are:
Am I correct to use a MutableList within the function and simply return it (even though the function's type is List)?
Do I need to create a local MutableList variable? Do I need any local "list" variable? I am used to (again, Delphi) doing something like:
function firstTenInts: TStringList;
var
i: integer;
begin
result.Clear;
for i := 1 to 10 do
result.Add(IntToStr(i));
end;
which requires no "new" local variable. I simply "work" result which is very similar to Kotlin's return value except that it serves as a local variable of the function's type which can be "worked" throughout the function.
Is there no way to manipulate a Kotlin function's return value other than with another (locally created) variable?
Finally, I can rest assured that any local variables I create are destroyed when the function ends even though I'm "passing them back" - correct?
P.S. I know this is an absurd way to create a List of 10 integers. I am using this only as a framework for the questions/issues I have detailed above. Assume that the returned List will be of unknown size.
(Please do not suggest better ways of creating this list of integers; that is not what I am asking about).
Am I correct to use a MutableList within the function and simply return it (even though the function's type is List)?
Generally that's ok. You do such things if you require a list that can be mutated within the function but from outside you do not want it to be easily mutable (which doesn't mean that it isn't mutable; you could still cast it to a mutable list, i.e. firstTenInts() as MutableList would work and so you could also mutate it again).
Whether you need that mutable list in the function or not actually depends on you. For example just calling listOf(1, 2, 3) will return you a List<Int> immediately, i.e. fun first3Ints() = listOf(1,2,3) will immediately return a List<Int>.
Do I need to create a local MutableList variable? Do I need any local "list" variable? I am used to (again, Delphi) doing something like:
You do not need to, but you can. It's up to you what better suites your needs. This also applies to your local list variable. You do not necessarily need one, even though you will have one nonetheless under the hood. Example:
fun first3Ints() = listOf(1, 2, 3)
translates to something like the following:
fun first3Ints() : List<Int> {
val result = listOf(1, 2, 3)
return result
}
On smaller functions you at least can spare some variable declarations using direct assignments. You can also use something like apply, also, let, run or with to overcome val/var, e.g. (just simulating... all variants can be implemented easier):
fun first3Ints() = arrayListOf().apply {
add(1) // apply allows calling all methods of the receiver directly.. (receiver = arrayListOf...)
add(2)
add(3)
}
fun first2Ints() = arrayListOf().also { // similar to apply, but now there is an 'it' available... you could also name that variable differently, e.g. using .also { result -> result.add(1) }
it.add(1)
it.add(2)
}
Is there no way to manipulate a Kotlin function's return value other than with another (locally created) variable?
So this becomes yes (even though .. technically speaking there will be one)... it is possible, but you need to specify on what you basically want to operate, except for the case where you implement an extension function. Then this within the extension function actually becomes the object you called the function on.
Finally, I can rest assured that any local variables I create are destroyed when the function ends even though I'm "passing them back" - correct?
... yes and no. Yes, you can rest assured that any local variable will be garbage collected when need arises (except you are doing something very special). And there is also the no: you don't know when they will be destroyed. Regarding your returned value it is even more special: you are actually getting only a reference to an object, not the object itself... so somehow you basically get that local variable back. You may want to have a look at JVM / stack and heap and how the objects are referenced and stored...
Your return is right and you can use ArrayList instead of mutableListOf and there will be no problem...
but still I didn't understand your main problem but the main topic you were talking about shows that you want to be sure of using the list as a return and that is right man
There are various ways for creating ArrayList of 10 items (just as an example you given). You can find below code snippet such as example :
// directly returning array list as Kotlin has functionality to define such kind of function just like macros
fun firstTenInts(): List<Int> = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// Or by using standard function apply
fun firstTenInts(): List<Int> = ArrayList<Int>().apply {
for (i in 1..10)
this.add(i)
}
// Or by declaring variable of ArrayList
fun firstTenInts(): List<Int> {
val iList = ArrayList<Int>()
for (i in 1..10)
iList.add(i)
return iList
}
// Or by using standard function with
fun firstTenInts(): List<Int> = with(ArrayList<Int>()) {
for (i in 1..10)
this.add(i)
return#with this
}
Above are the various examples defines how you can do differently (Although sample you provided is also a valid example).
I am trying to use the put method of the ContentValues class in the Android API from Scala, but I can't figure out a way to make Scala narrow down the type of list elements. For example :
val a: List[(String, Any)](...)
val cv = new ContentValues
for ((k,v) <- a) cv.put(k,v)
...yields an error that roughly says it can't resolve the "overloaded put method with alternatives put(String, String), put(String, Int),...".
My intuition is telling me I should probably use reflection, but I can't figure out how to do it exactly. Any pointer?
The type of your list is too imprecise. ContentValues.put has overloads for a number of types, but they are all specific (Integer, Float, etc.), and no alternative for Object.
You can:
make the list type more precise, in case the list has only elements of one type (say, Int).
use an HList, but beware of type wizardry. It may be overkill in this case
as a last resort, do a type test:
for ((k, v) <- a) v match {
case n: Int => cv.put(k, v)
case d: Double => cv.put(k, d)
//...
}
This is a very famous and common problem in Scala. The type system works correctly, and developers are simply not used to it.
In strongly typed programming languages the compiler verifies rules on the types you are using and this prevents painful runtime errors. If you use reflection or casts you are allowed to force the type system and this can produce unexpected errors and problems at runtime.
Why would you want to break the rules which you largely benefit from ? A good reason is when you are designing a library and you know exactly what is going to happen in your internals (see scala collections).
When you end up using types such as Any or AnyRef you should be worried and ask yourself:
why I am going so up in the hierarchy ?
Am I probably using an anti pattern or a bad constructor for a strongly typed programming language?
In fact I guess you are, and I propose we further investigate together why you have a List[(String,Any)]. Let's assume you had no problems in putting data into the ContentValues , what if later you would need to extract something from there? How would you know if it was an Int, a Double, a Float?