Not able to print the value of a key of a Map in Kotlin - kotlin

I'm fairly new to Kotlin. I want to print the count of a character in a string. For this, I'm using Kotlin's groupingBy() function and applying eachCount() to it.
My code:
val str = "0100101101010"
val countMap : Map<Char, Int> = str.groupingBy { it }.eachCount()
println(countMap["1"])
But I'm getting this error in the console: Type inference failed. The value of the type parameter K should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
Can someone explain to me what I'm doing wrong here?

"1" is a string literal, but your map has characters as keys. You should use the character literal '1':
println(countMap['1'])
The reason for that confusing error message is because it is trying to call this get overload, which is generic. It tries to infer the generic type arguments, and fails.

Related

Safely casting jOOQ's TableField<*, *> to TableField<*, {some object type}> in Kotlin

So I have this function in Kotlin:
fun getJooqOperator(field: TableField<*,*>, value: String): org.jooq.Condition {
// In this case, "this" is the operator enum.
// The combination of field and operator is strictly handled in the front-end (Elm)
return when (this) {
EQ -> (field as TableField<*, String>).eq(value)
NEQ -> (field as TableField<*, String>).ne(value)
GT -> (field as TableField<*, Int>).gt(Integer.parseInt(value))
}
}
This piece is used in a Kotlin class that will deserialize some JSON from the front-end. From this JSON, the class will build a jOOQ-query based on the input from the user. This part is about using the correct operator with the corresponding column and input value.
However this will not result in compile errors, IntelliJ is complaining about the casting of the field. I know for sure that these fields can be casted safely for the specific operator enum. This is the warning IntelliJ throws:
I don't want to Change type arguments to <*, *>, because without the casting, the jOOQ-condition won't work with the values.
Is there a way to rewrite my function properly, or can I safely ignore these warnings?
Casting
[...] or can I safely ignore these warnings?
I'm not sure what kinds of safety you're expecting here. Your assumption that EQ and NEQ are String based, whereas GT is Int based is quite a strong one. You probably have your reassons for this. If you encode things this way, and know why that is, then yes, you can safely ignore the warnings. This doesn't translate to such casts being "safe" in general, they're not. The * translates to any unknown type, yet in your cast, you make an assumption that effectively, the type should have been known, it's just not possible to express it in your type system.
Coercion
You can always use data type coercion as well, e.g.
return when (this) {
EQ -> field.coerce(SQLDataType.VARCHAR).eq(value)
NEQ -> field.coerce(SQLDataType.VARCHAR).ne(value)
GT -> field.coerce(SQLDataType.INTEGER).gt(Integer.parseInt(value))
}
Although, that does have an effect on the expression tree you're building, unlike the unsafe cast. Probably not an important effect in your case.

What happens under the hood when we define a type alias with a type variable in Elm

Suppose we define a type alias say Message as:
type alias Message a =
{ code : String
, body : a
}
And later define a function readMessage as:
readMessage : Message () -> String
readMessage message =
...
The above example is from Elm tutorial and book says:
This function takes Message with an empty body. This is not the same
as any value, just an empty one.
Can someone please elaborate what exactly happens in above scenario and how compiler handles it.
Unless you really want to see the internal compiler representation of that, I think what's important here is the difference between any value and empty value.
Message a is a parametrized type with 1 parameter. You can read it as a template, e.g. wherever lowercase a appears in the definition of the Message it will be substituted with the concrete type (String, Int, etc).
So this is how function should look like if we want it to take a Message with String body:
readMessage : Message String -> String
readMessage message =
What happens here is that the type of body field is no longer an a but a String (a is substituted with String):
{ code : String
, body : String
}
The value of nothing (aka void or unit) in Elm is encoded as (). That's why a Message with empty body value looks like this:
{ code : String
, body : ()
}
But when we simply don't care about the body value we can just take a Message with any value:
readMessage : Message a -> String
readMessage message =
The lowercase a can be any lowercase string, we can make it more readable like this:
readMessage : Message any -> String
readMessage message =
But then we cannot really read message body, because we don't know the type of it (so we don't know how to read it).
Hope that helps.
The type Message () is an alias for the following record:
{ code : String
, body : ()
}
where the () type denotes a tuple without any items (also known as null tuple). There is only one value of such type and it is also written ().
Now, when we want to omit some field in a record, we cannot just not specify it – that would make the compiler rightly mad, see also The Billion Dollar Mistake. We need to tell the compiler that the value can be omitted.
One way we could do it is to use the Maybe type but if we made a list of messages that would allow us to include the body in some messages and omit it in others. This might not be what we want.
The alternative is to parametrize the Message type as you are doing in the question. This will allow us to have a messages with String bodies when reading the message, and with a different body type when we are not interested in the body.
In this case, we need to consider what the body type should be. While we could use an empty Strings for messages with omitted bodies, they would be easily confused with messages with empty bodies. We could also use Bool but then we would need to decide if we want to use True or False for the omitted value. Finally, we can use the null tuple; since it only has one possible value it is ideal for us.
There is actually one more possibility: we could create a type alias MessageWithoutBody = { code: String }. This is cleaner in some cases (especially when you need to omit more fields) but can be more verbose as you need to duplicate all the fields you want to keep.

Kotlin: How to handle function of Any input type and given output type

I have functions with signature (ShellInput) -> ShellOutput. Reference to these is stored in a map:
mutableMapOf<String, (ShellInput) -> ShellOutput>("trim" to ::trim)
These are then fetched from this map and invoked via reflection. Now there's a need to have functions where input type can vary, so I tried:
mutableMapOf<String, (Any) -> ShellOutput>("trim" to ::trim)
But this does not work. How can I handle this?
In fact, putting ::trim as a value into a mutableMapOf<String, (Any) -> ShellOutput> would break type safety: when you take a value out of the map afterwards, it is typed as (Any) -> ShellOutput, letting you to pass Any as an argument to the function. The type system does not allow that.
As a workaround you can use a star-projected type Function1<*, ShellOutput>, which means that the argument type is unknown:
mutableMapOf<String, Function1<*, ShellOutput>>("trim" to ::trim)
When you get a value from this map, you'll see that the argument type the function accepts is Nothing. This is totally expected, the type system again preserves type safety: there is nothing you can safely pass to a function with an unknown parameter type (Nothing is the type with no values).
Now it's time for you to show the compiler that you know more about the types than it does, by using an unchecked cast:
#Suppress("UNCHECKED_CAST")
val trim = functions["trim"] as Function1<ShellInput, ShellOutput>
You can encapsulate the cast into an extension, like this:
#Suppress("UNCHECKED_CAST")
fun <T> Map<String, Function1<*, ShellOutput>>.getWithParameter(key: String):
Function1<T, ShellOutput> =
get(key) as Function1<T, ShellOutput>
// Usage:
functions.getWithParameter<ShellInput>("trim")
Alternatively, use KFunction<ShellOutput>. It will save you from unchecked casts, but it is less safe right from the start as it does not control the number of arguments, you can .call(...) such function references with any number of arguments of any type.

Cast Any to Array in Kotlin

I'm initializing a class by loading data from a Map<String, Any> in Kotlin. As this Map is gleaned directly from JSON, I don't know for certain that any given key exists, or that its value is of the type I expect. To unpack this Map safely I'm doing the following, which appears to work perfectly:
a = rawData["A"] as? String ?: ""
Some of this data is in further nested JSON, which I'm unpacking to Arrays; I've tried to do this in the same way:
b = rawData["B"] as? Array<String> ?: arrayOf<String>()
However, when I attempt this using an array (as above) IntelliJ kicks up a fuss, saying
Warning:(111, 30) Kotlin: Unchecked cast: Any? to Array<String>
Is this just the IDE getting itself in a twist or is this method genuinely unsafe for Arrays despite being seemingly perfectly safe for other types?
For any future readers of this question, to expand on the accepted answer with a solution:
To safely cast Any to an array of a particular type in Kotlin, you have to first cast to an untyped array (see zsmb13's answer above for why), and then filter that array to the desired type.
For example, to cast input: Any to an array of String instances, you would call:
val inputAsArray = (input as? Array<*>)?.filterIsInstance<String>()
I was ready to call this a bug, because Array is a reified type, meaning its generic parameter can actually be checked at runtime (unlike a List, for example). I've tried looking to see if it's been filed yet, and it turns out the compiler is actually right to show you a warning. As you can see in the response to this issue, there's still a nullability problem with casts of this kind.
val a = arrayOf("foo", "bar", null) as Array<String>
println(a[2].length)
Arrays like the one in this example are successfully cast (using as, they don't throw an exception, using as?, they don't return null), however, the cast can not ensure that this is an Array<String>, only that it's an Array<String?>.
This means that you can later read null values from a variable that is typed as an Array<String> after the cast, with no further warnings from the compiler.

Exclamation operator?

I'm learning D and have seen a lot of code like this:
ushort x = to!ushort(args[1]);
I assume this casts args[1] to ushort, but what's the difference between this and cast(ushort)?
EDIT: And what other uses does the exclamation mark operator have?
In D,
to!ushort(args[1])
is shorthand for the template instantiation
to!(ushort)(args[1])
and is similar to
to<ushort>(args[1])
in languages like C++/Java/C#.
The exclamation point is to note the fact that it's not a regular argument, but a template argument.
The notation does not use angle brackets because those are ridiculously difficult to parse correctly for a compiler (they make the grammar very context-sensitive), which makes it that much more difficult to implement a correct compiler. See here for more info.
The only other use I know about is just the unary 'not' operation (e.g. false == !true)... I can't think of any other uses at the moment.
Regarding the cast:
cast(ushort) is an unchecked cast, so it won't throw an exception if the value is out of range.
to!ushort() is a checked cast, so it throws an exception if the value is out of range.
The exclamation mark here is not an operator, it is just a token part of the explicit template instantiation syntax (described in detail here).
std.conv.to (docs) is a function template for converting between arbitrary types. It is implemented entirely in the library and has no special support in the language. It has a broader and different scope compared to the cast operator.
The to template takes two type parameters; a "to" type and a "from" type, in that order. In your example, the template is explicitly instantiated with the single type argument ushort for the "to" parameter, and a second type argument string (assuming args comes from the first parameter to main) is automatically inferred from the regular function argument passed to the function (args[1]) as the "from" parameter.
The resulting function takes a string parameter and returns a ushort parsed from that string, or throws an exception if it failed. The cast operator will not attempt this kind of high-level conversion.
Note that if there is more than one explicit template parameter, or that parameter has more than one token in it (ushort is a single keyword token), you must wrap the template parameter list in parentheses:
ushort result;
result = to!(typeof(result))(args[1]);
In this example, typeof, (, result and ) are four separate tokens and the parentheses are thus required.
To answer your last question, the ! token is also used for the unary not operator, unrelated to template instantiations:
bool yes = true;
bool no = !yes; // 'no' is false
You already got two excellent answers by jA_cOp and Merhdad. I just want answer directly to the OP question (what's the difference between this and cast(ushort)?) - The difference is that cast(ushort)args[1] will not work (you cannot cast from a string to an uint just like that), while the to!(type)(param) template knows what to do with the string and how to convert it to the primitive type.