I'm currently writing a generator for the ABAP language and I'm facing one problem.
In the service that I have to transform I have the following object:
"router_options": {
"track": true,
"motorway": true,
"toll": true,
"trailers": 0,
"weight": 0,
"weight_per_axle": 0,
"height": 0,
"width": 0,
"length": 0,
"hazardous_goods": "explosive",
"max_walk_distance": 0,
"approach": "unrestricted",
"snap": 0,
"strict_restriction": true
}
when I execute the codegen generator the code generated give me the following code
i_router_options_track type bool optional
i_router_options_motorway type bool optional
i_router_options_toll type bool optional
i_router_options_trailers type int optional
i_router_options_weight type float optional
i_router_options_weight_per_axle type float optional
i_router_options_height type float optional
i_router_options_width type float optional
i_router_options_length type float optional
i_router_options_hazardous_goods type string optional
i_router_options_max_walk_distance type float optional
The approach would be more something like declaring a type of structure in the operation part like that
types : begin of ts_router_options,
track type bool,
motorway type bool,
toll type bool,
trailers type int,
weight type float,
weight_per_axle type float,
height type float,
width type float,
length type float,
hazardous_goods type string,
max_walk_distance type float,
approach type string,
snap type float,
strict_restriction type bool,
end of ts_router_options.
and use it like below :
data : router_options type ts_router_options.
router_options-height = '10,10'
Does anyone can help me for that ?
Related
In the below code:
val sum = listOf(1, 2, 3).sumOf { if (it % 2 == 0) 1 else 0 }
Kotlin gives the following error:
Kotlin: Overload resolution ambiguity:
public inline fun <T> Iterable<TypeVariable(T)>.sumOf(selector: (TypeVariable(T)) -> Int): Int defined in kotlin.collections
public inline fun <T> Iterable<TypeVariable(T)>.sumOf(selector: (TypeVariable(T)) -> Long): Long defined in kotlin.collections
Playground
If I explicitly use toInt(), the error is gone but I get a warning of redundant call
val sum = listOf(1, 2, 3).sumOf { if (it % 2 == 0) 1.toInt() else 0 }
Why doesn't Kotlin automatically use Int here?
The spec says the following about the types of integer literals:
A literal without the mark has a special integer literal type
dependent on the value of the literal:
If the value is greater than maximum kotlin.Long value, it is an illegal integer literal and should be a compile-time error;
Otherwise, if the value is greater than maximum kotlin.Int value, it has type kotlin.Long;
Otherwise, it has an integer literal type containing all the built-in integer types guaranteed to be able to represent this value.
So integer literals like "1" doesn't have a simple type like kotlin.Int or kotlin.Long. It has an "integer literal type".
Example: integer literal 0x01 has value 1 and therefore has type ILT(kotlin.Byte,kotlin.Short,kotlin.Int,kotlin.Long). Integer literal 70000 has value 70000, which is not representable using types kotlin.Byte and kotlin.Short and therefore has type ILT(kotlin.Int,kotlin.Long).
Here are the subtyping rules of these ILTs. Importantly for your question:
∀Ti∈{T1,…,TK}:ILT(T1,…,TK)<:Ti
This rule basically says that ILTs work like an intersection type. For example, ILT(kotlin.Int,kotlin.Long) is a subtype of kotlin.Int and also a subtype of kotlin.Long.
Now let's look at your lambda { if (it % 2 == 0) 1 else 0 }. It returns either the literal 0 or the literal 1. These both have the type:
ILT(kotlin.Byte,kotlin.Short,kotlin.Int,kotlin.Long)
which is a subtype of kotlin.Long and kotlin.Int. Therefore, your lambda can be converted to both a (T) -> Long and a (T) -> Int, in the same way that a (T) -> Dog can be converted to a (T) -> Animal.
When you use toInt(), then only the (T) -> Int overload matches the return type, since Int is not convertible to Long implicitly.
Apparently, if you do toInt() on the whole expression, there is no redundant toInt warning:
fun main() {
val sum = listOf(1, 2, 3).sumOf { (if (it % 2 == 0) 1 else 0).toInt() }
}
Also note that the compiler looks at the lambda return type only because sumOf is annotated with OverloadResolutionByLambdaReturnType. If not for this, you would still get an ambiguity error even if you use toInt(). See Using lambda return type to refine function applicability for more info.
The reason why it is able to choose the Int overload in simple cases like:
fun foo(x: Int) {}
fun foo(x: Long) {}
fun main() { foo(43) }
is because of the "Choosing the most specific candidate" step in overload resolution. In this step, it handles built in numeric types differently, and considers Int the "most specific". However, this step happens just before "Using lambda return type to refine function applicability", and thinks that (T) -> Int and (T) -> Long are equally specific.
Why does this work (using signed types)...
val x = 123
println(x in Byte.MIN_VALUE..Byte.MAX_VALUE)
...but this doesn't (using unsigned types)...
val x = 123
println(x in UByte.MIN_VALUE..UByte.MAX_VALUE)
Error produced is:
Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
So Byte.MIN_VALUE..Byte.MAX_VALUE creates an IntRange (there is no ByteRange). And x is an Int here so it can work.
UByte.MIN_VALUE..UByte.MAX_VALUE returns a UIntRange, so you would need to declare x as a UInt type:
val x = 123U
I don't undertand how to specify the default value for `ByteArray.getOrElse() function.
I tried:
myInt = dat.getOrElse(0, 0).toInt()
but compiler complains with the following error:
The integer literal does not conform to the expected type (Int) -> Byte
How to specify the default value?
The expected type of the second argument (defaultValue) is (Int) -> Byte which is a lambda that takes an Int and returns a Byte.
myInt = dat.getOrElse(index = 100, defaultValue = {
i ->
// use i to calcuate your Byte that should be returned...
// or return a fixed value
i * 1 // for example
})
Signature of getOrElse:
fun ByteArray.getOrElse(
index: Int,
defaultValue: (Int) -> Byte
): Byte
The second argument is a function literal
myInt = dat.getOrElse(100, { /** what is there is no element 100*/ 0 })
I have tried using Int and Integer types in Kotlin.Although I don't see any difference.
Is there a difference between Int and Integer types in Kotlin?Or are they the same?
Int is a Kotlin Class derived from Number. See doc
[Int] Represents a 32-bit signed integer. On the JVM, non-nullable values of
this type are represented as values of the primitive type int.
Integer is a Java Class.
If you were to search the Kotlin spec for "Integer", there is no Kotlin Integer type.
If you use the expression is Integer in IntelliJ, the IDE warns...
This type shouldn't be used in Kotlin, use Int instead.
Integer will interoperate well with Kotlin Int, but they do have some subtle differences in behavior, for example:
val one: Integer = 1 // error: "The integer literal does not conform to the expected type Integer"
val two: Integer = Integer(2) // compiles
val three: Int = Int(3) // does not compile
val four: Int = 4 // compiles
In Java, there are times where you need to explicitly "box" an integer as an object. In Kotlin only Nullable integers (Int?) are boxed. Explicitly trying to box a non-nullable integer will give a compiler error:
val three: Int = Int(3) // error: "Cannot access '<init>': it is private in 'Int'
val four: Any = 4 // implicit boxing compiles (or is it really boxed?)
But Int and Integer (java.lang.Integer) will be treated the same most of the time.
when(four) {
is Int -> println("is Int")
is Integer -> println("is Integer")
else -> println("is other")
} //prints "is Int"
when(four) {
is Integer -> println("is Integer")
is Int -> println("is Int")
else -> println("is other")
} //prints "is Integer"
A Int is a primitive Type. This is equivalent to JVM int.
A nullable Int Int? is a boxed Type. This is equivalent to java.lang.Integer.
Just have a look at https://kotlinlang.org/docs/reference/basic-types.html#representation
On the Java platform, numbers are physically stored as JVM primitive
types, unless we need a nullable number reference (e.g. Int?) or
generics are involved. In the latter cases numbers are boxed.
That means, that Int is represented as primitive int. Only in cases when nullability or generics are involved, the backing Wrapper Type Integer must be used.
If you use Integer from the beginning, you always work with the wrapper type and never with the primitive int.
As seen another question in 0xFF0000FF An integer literal does not conform to the expected type kotlin.Int
I declaring value 0xFF as Byte
val b:Byte = 0xFF
receiving The integer literal does not conform to the expected type Byte compile error
Since I have clue about kotlin.Byte is signed byte
How to declaring Byte in Kotlin with 0x00 - 0xFF unsigned byte just like .net Byte b = 0xFF ?
.
.
If you want instant compiler for testing and answer:
rextester , try.kotlinlang.org
Kotlin doesn't automatically convert between number types.
If you do val b:Byte = 0xFF.toByte() then it compiles and results in a byte with value -1.
If you want to hold the unsigned byte value then you need to store it as a Char, but you will need to convert it to another type to print it as a number:
val b = 0xFF.toChar()
println(b.toInt())
Kotlin now supports unsigned integer types:
val b: UByte = 255u
val c: UByte = 0xFFu