I start with one map myInitialMap. i would like to create another map myNewMap that is initialised with myInitialMap.
val myInitialMap = mapOf<String, Int>("one" to 1, "two" to 2)
val myNewMap = mapOf(myInitialMap)
I get error:
Type mismatch.
Required: Pair<TypeVariable(K), TypeVariable(V)>
Found: Map<String, Int>
How can I initialise myNewMap with myInitialMap?
You can use myInitialMap.toList().toMutableStateMap().
The ...Of() functions in Kotlin all follow the convention of taking individual entries as varargs, which is why mapOf(myInitialMap) doesn't, and shouldn't, work. Since these functions use the arguments to determine the generic types, the list/set versions could not possibly support also having overloads that accept an Iterable parameter with all the entries to include, because you might actually want a list of Iterables (2D collection). For consistency, mapOf must behave the same.
Function naming/behavior conventions:
...Of(): A function taking a vararg parameter of all the individual values to put in the collection. The argument type can be used for the compiler to infer the generic type(s) of the collection.
.to...Map/Set/List(): An extension function that creates a shallow copy or new type of collection from the entries of the collection it is called on.
.as...(): An extension function that wraps the original object in another one. For example, asIterable() or asSequence() will return those types, but they will read from the original object. They are not copies.
Related
I'm wondering why I can pass a contravariance in a covariance type example of the List
I created this interface as you can see I is a contravariance but I was able to pass to the list
interface ListMapper<in I, out O> : Mapper<List<I>, List<O>>
if you check you will see that the list accept a Covariance type
public interface List<out E> : Collection<E> {...}
Why and how can this be possible ?
Presumably, the first type in the Mapper interface is contravariant at the declaration site.
There's no reason for the restriction you're imagining should be there. The covariance of the List is internal to the List functionality, and has nothing to do with the Mapper's functionality.
A List is covariant, meaning it cannot consume any T, so maybe it will simplify your understanding to replace it with a non-generic class that doesn't consume anything, such as Int, which is immutable. It looks obviously acceptable logically:
interface IntMapper : Mapper<Int, Int>
It's no different than with the List. You have a type that doesn't consume anything, yet it can be the input for a Mapper.
Answering your follow-up question from the comment:
The K type of HashMap is invariant at the declaration site. To simplify this dicussion, let's just use MutableList which also has an invariant type (so we aren't confused by Map's second V type).
Let's also simplify and use a more basic interface that just consumes, so we aren't confused by the second type in Mapper:
interface Consumer<in I>
So now we have:
// Allowed:
class ListConsumer<in I> : Consumer<List<I>>
// Not allowed:
class MutableListConsumer<in I> : Consumer<MutableList<I>> // Compile error
Imagine you have a ListConsumer. Since ListConsumer is contravariant, it allows you to cast a ListConsumer<Number> to the more restrictive type ListConsumer<Int>:
val numberListConsumer: ListConsumer<Number> = //...
val intListConsumer: ListConsumer<Int> = numberListConsumer
This makes sense. If you can consume List<Number>, then it is safe to consume any List<Int> because a List<Int> is also a List<Number> due to List's covariant type.
But it doesn't make sense with MutableList. A MutableList<Int> is not a MutableList<Number> because MutableList's type is invariant.
I develop the flutter package and in this package one of class get function argument.
When I use this package in another flutter app, I can send function as prop to this package .
Now I just want to learn if I use the flutter module and build the aar , how can I send function as prop in native android ?
Thanks
This is not possible because you can send only serializable types
By default, AIDL supports the following data types:
All primitive types in the Java programming language (such as int, long, char, boolean, and so on)
Arrays of primitive types such as int[]
String
CharSequence
List
All elements in the List must be one of the supported data types in
this list or one of the other AIDL-generated interfaces or parcelables you've declared. A List may optionally be used as a parameterized type class (for example, List). The actual concrete class that the other side receives is always an ArrayList, although the method is generated to use the List interface.
Map
.
All elements in the Map must be one of the supported data types in this list or one of the other AIDL-generated interfaces or parcelables you've declared. Parameterized type maps, (such as those of the form Map<String,Integer>) are not supported. The actual concrete class that the other side receives is always a HashMap, although the method is generated to use the Map interface. Consider using a Bundle as an alternative to Map.
For more detailed information you can refer to the official AIDL documentation
I've seen people using ViewModelProvider[Someclass::class.java] instead of ViewModelProvider.get(Someclass::class.java), and it compiles in Android Studio. The problem is that I couldn't find any documentation of such usage online.
With kotlin you can add operator modifiers to your function. So if you have some class with a get function and you might want to access it with [], like an array or map, you could add operator modifier.
Square brackets are translated to calls to get and set with appropriate numbers of arguments.
So this only works for functions with name get or set!
class Provider {
operator fun get(key: String)
operator fun set(key: String, value: String) { ... }
}
Then you can call the function like:
Provider().get("key") // IDE hint: should be replaced with indexing operator
Provider()["key"] // calls get()
Provider().set("key", "value") // IDE hint: should be replaced with indexing operator
Provider()["key"] = "value" // calls set()
Reference
See Kotlin Operator overloading
Kotlin allows operator overloading by marking a function as an operator function. The square brackets notation is one of these operators (indexed access operator).
Kotlin automatically interprets Java functions as operator functions if their name and signature match the requirements of a Kotlin operator function. In this case, it interprets functions named get as an "indexed access operator" if they return something, which allows you to use square bracket notation.
ViewModelProvider[Someclass::class.java] is a shorter version of ViewModelProvider.get(Someclass::class.java) there is no differences.
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).
For one permission I can use permissionsdispatcher in java and kotlin - but when it comes to multiple permissions like this:
#NeedsPermission({Manifest.permission.BLUETOOTH_ADMIN,Manifest.permission.BLUETOOTH})
I get a problem on kotlin - it does not accept more than one parameter there - works fine with java
In Java the {} represents creating an array, and in this context in Kotlin the {} is accidentally creating a lambda expression and it cannot be determined what you intend because the code inside the lambda is invalid.
So you are saying #NeedsPermission(someFunctionReferenceThatIsInvalid) instead of passing in an array of permissions as #NeedsPermission(array)
In the annotation the array is being treated as a vararg so you can just list the elements:
#NeedsPermission(Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH)
If it were being treated as an array, you would use the arrayOf function:
#NeedsPermission(arrayOf(Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH))
The examples creating an array and then using the * spread operator are basically doing and then undoing the array and it is not necessary.
#NeedsPermission(arrayOf(Manifest.permission.BLUETOOTH_ADMIN,Manifest.permission.BLUETOOTH))
In java #NeedsPermission({...}) the curly brackets {...} is just a shorthand for creating an array. In kotlin you must explicitly say that it is an array, because {} is reserved for lambda expressions.