Switch on a Byte - switch-statement

How can I switch on a Byte value? The obvious way would be:
fun foo(b: Byte): Boolean {
return when(b) {
0 -> true
else -> false
}
}
but that fails at compile time with
src/ByteSwitch.kt:3:5: error: incompatible types: kotlin.Int and kotlin.Byte
0 -> true
^
Is there a way to make that 0 be a byte literal?

Since Kotlin allows branch conditions to be arbitrary expressions (not necessarily constants), one approach is to accept that the 0 will be an Int and simply convert it explicitly to a Byte:
fun foo(b: Byte): Boolean {
return when(b) {
0.toByte() -> true
else -> false
}
}
Per Ilya, "0.toByte() is evaluated at compile time, so there's no cost of conversion at runtime."

You cannot specify a byte literal in Kotlin (nor can you in Java). From Literal Constants - Basic Types - Kotlin Programming Language
There are the following kinds of literal constants for integral
values:
Decimals: 123
Longs are tagged by a capital L: 123L
Hexadecimals: 0x0F
Binaries: 0b00001011
You can however declare compiler-time constants to avoid run-time overhead:
const val ZERO_BYTE: Byte = 0
fun foo(b: Byte): Boolean {
return when (b) {
ZERO_BYTE -> true
else -> false
}
}
Inspecting the Kotlin bytecode further reveals that as 0.toByte() can be determined at compile-time you can in fact inline the evaluation with no additional run-time overhead:
fun foo(b: Byte): Boolean {
return when (b) {
0.toByte() -> true
else -> false
}
}

Related

Groovy primitive double arithmetic

This yields 127
double middle = 255 / 2
While this yields 127.5
Double middle = 255 / 2
Meanwhile this yields 127.5 as well
double middle = (255 / 2) as double
I know that Groovy operates with BigDecimal per default, but to me this is a Huuge bug! How can this be?
This actually has nothing to do with BigDecimals, but rather with the type coercion from primitive integer to the primitive double. This problem is caused by the Groovy compiler and the (most probably) incorrect bytecode it produces. Take a look at the following bytecode representation of the first case. The following Groovy code:
void ex1() {
double x = 255 / 2
println x
}
gets compiled to a bytecode that can be represented as:
public void ex1() {
CallSite[] var1 = $getCallSiteArray();
double x = 0.0D;
if (BytecodeInterface8.isOrigInt() && BytecodeInterface8.isOrigD() && !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()) {
int var5 = 255 / 2;
x = (double)var5;
} else {
Object var4 = var1[5].call(255, 2);
x = DefaultTypeTransformation.doubleUnbox(var4);
}
var1[6].callCurrent(this, x);
}
It shows that in this case, it is not possible to get 127.5 as a result, because the result of 255 / 2 expression is stored in the variable of type int. It feels like this is an example of inconsistent behavior because here is what the bytecode of the method that uses Double looks like:
public void ex2() {
CallSite[] var1 = $getCallSiteArray();
Double x = null;
if (BytecodeInterface8.isOrigInt() && !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()) {
Object var4 = var1[8].call(255, 2);
x = (Double)ScriptBytecodeAdapter.castToType(var4, Double.class);
} else {
Object var3 = var1[7].call(255, 2);
x = (Double)ScriptBytecodeAdapter.castToType(var3, Double.class);
}
var1[9].callCurrent(this, x);
}
The main problem with this use case is that adding #TypeChecked does not prevent you from making this mistake - compilation passes and the incorrect result is returned. However, when we add #TypeChecked annotation to the method that uses Double the compilation error is thrown. Adding #CompileStatic solves the problem.
I've run some tests and I can confirm that this problem exists in the recent 2.5.6, as well as 3.0.0-alpha-4 versions. I've created a bug report in the Groovy JIRA project. Thanks for finding and reporting the problem!
UPDATE: Java does the same
It seems like this is not a Groovy bug - this is how Java does things as well. In Java, you can store a result of a division of two ints in the double variable, but you will get nothing else than an integer cast to the double. With {{Double}} type things are different in terms of the syntax but pretty similar in terms of the bytecode. With {{Double}} you need to explicitly cast at least one part of the equation to the {{double}} type, which results in the bytecode that casts both integers to the {{double}}. Consider the following example in Java:
final class IntDivEx {
static double div(int a, int b) {
return a / b;
}
static Double div2(int a, int b) {
return a / (double) b;
}
public static void main(String[] args) {
System.out.println(div(255,2));
System.out.println(div2(255,2));
}
}
When you run it you get:
127.0
127.5
Now, if you take a look at the bytecode it creates, you will see something like this:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
final class IntDivEx {
IntDivEx() {
}
static double div(int a, int b) {
return (double)(a / b);
}
static Double div2(int a, int b) {
return (double)a / (double)b;
}
public static void main(String[] args) {
System.out.println(div(255, 2));
System.out.println(div2(255, 2));
}
}
The only difference (in terms of the syntax) between Groovy and Java is that Groovy allows you to implicitly cast an integer to Double, and that is why
Double x = 255 / 2
is the correct statement in Groovy, while Java, in this case, fails during the compilation with the following error:
Error:(10, 18) java: incompatible types: int cannot be converted to java.lang.Double
That is why in Java you need to use casting when you assign from integer to Double.

Split string every n characters

What would be an idiomatic way to split a string into strings of 2 characters each?
Examples:
"" -> [""]
"ab" -> ["ab"]
"abcd" -> ["ab", "cd"]
We can assume that the string has a length which is a multiple of 2.
I could use a regex like in this Java answer but I was hoping to find a better way (i.e. using one of kotlin's additional methods).
Once Kotlin 1.2 is released, you can use the chunked function that is added to kotlin-stdlib by the KEEP-11 proposal. Example:
val chunked = myString.chunked(2)
You can already try this with Kotlin 1.2 M2 pre-release.
Until then, you can implement the same with this code:
fun String.chunked(size: Int): List<String> {
val nChunks = length / size
return (0 until nChunks).map { substring(it * size, (it + 1) * size) }
}
println("abcdef".chunked(2)) // [ab, cd, ef]
This implementation drops the remainder that is less than size elements. You can modify it do add the remainder to the result as well.
A functional version of chunked using generateSequence:
fun String.split(n: Int) = Pair(this.drop(n), this.take(n))
fun String.chunked(n: Int): Sequence<String> =
generateSequence(this.split(n), {
when {
it.first.isEmpty() -> null
else -> it.first.split(n)
}
})
.map(Pair<*, String>::second)
Output:
"".chunked(2) => []
"ab".chunked(2) => [ab]
"abcd".chunked(2) => [ab, cd]
"abc".chunked(2) => [ab, c]

Unknown parameter UInt8 in '_specialize attribute': Xcode 9

This code used for building bit pattern from array of bits gives me error in Xcode 9 (works in 8.3.3)
#_specialize(UInt8)
func integerFrom<T: UnsignedInteger>(_ bits: Array<Bit>) -> T {
var bitPattern: T = 0
for idx in bits.indices {
if bits[idx] == Bit.one {
let bit = T(UIntMax(1) << UIntMax(idx))
bitPattern = bitPattern | bit
}
}
return bitPattern
}
Error
Unknown parameter UInt8 in '_specialize attribute'
Any leads/suggestion on this?
You just need to include a where clause in the specialize definition like this
#_specialize(where T == UInt8)

Groovy Cast primitive type

I want to set fields dynamically in groovy so I have a java code that get datas from a database and I set groovy fields using Bindings.setVariable() in java.
I would like to know if it is possible to cast each primitive types in groovy.
String to int, String to float and so on.
So I could always send a string and cast in an other primitive times, it depends of the type of my groovy fields.
#Opal's as solution is good, but I also wanted to mention that the Groovy JDK adds some convenient primitive check and conversion methods to CharSequence, which String implements:
isDouble and asDobule
isFloat and asFloat
isLong and asLong
isInteger and asInteger
Interestingly, it isFloat seems to be greedy, returning true for floating points beyond its range.
['2', '2.2', '2' * 10, "${Double.MAX_VALUE}"].each { s ->
switch (s) {
case { it.isInteger() }:
int i = s.toInteger()
println "String '$s' -> int $i"
break
case { it.isLong() }:
long l = s.toLong()
println "String '$s' -> long $l"
break
case { it.isFloat() }:
float f = s.toFloat()
println "String '$s' -> float $f"
break
case { it.isDouble() }:
double d = s.toDouble()
println "String '$s' -> double $d"
break
default:
println "$s is not a supported primitive"
}
}
prints out
String '2' -> int 2
String '2.2' -> float 2.2
String '2222222222' -> long 2222222222
String '1.7976931348623157E308' -> float Infinity
It depends on what you exactly need, but the following piece of code works well:
assert '2' as Integer == 2
assert '2.2' as Double == 2.2

Convert String.Index to Int or Range<String.Index> to NSRange

So I've found issues relating to the case of converting NSRange to Range<String.Index>, but I've actually run into the opposite problem.
Quite simply, I have a String and a Range<String.Index> and need to convert the latter into an NSRange for use with an older function.
So far my only workaround has been to grab a substring instead like so:
func foo(theString: String, inRange: Range<String.Index>?) -> Bool {
let theSubString = (nil == inRange) ? theString : theString.substringWithRange(inRange!)
return olderFunction(theSubString, NSMakeRange(0, countElements(theSubString)))
}
This works of course, but it isn't very pretty, I'd much rather avoid having to grab a sub-string and just use the range itself somehow, is this possible?
If you look into the definition of String.Index you find:
struct Index : BidirectionalIndexType, Comparable, Reflectable {
/// Returns the next consecutive value after `self`.
///
/// Requires: the next value is representable.
func successor() -> String.Index
/// Returns the previous consecutive value before `self`.
///
/// Requires: the previous value is representable.
func predecessor() -> String.Index
/// Returns a mirror that reflects `self`.
func getMirror() -> MirrorType
}
So actually there is no way to convert it to Int and that for good reason. Depending on the encoding of the string the single characters occupy a different number of bytes. The only way would be to count how many successor operations are needed to reach the desired String.Index.
Edit The definition of String has changed over the various Swift versions but it's basically the same answer. To see the very current definition just CMD-click on a String definition in XCode to get to the root (works for other types as well).
The distanceTo is an extension which goes to a variety of protocols. Just look for it in the String source after the CMD-click.
let index: Int = string.startIndex.distanceTo(range.startIndex)
I don't know which version introduced it, but in Swift 4.2 you can easily convert between the two.
To convert Range<String.Index> to NSRange:
let range = s[s.startIndex..<s.endIndex]
let nsRange = NSRange(range, in: s)
To convert NSRange to Range<String.Index>:
let nsRange = NSMakeRange(0, 4)
let range = Range(nsRange, in: s)
Keep in mind that NSRange is UTF-16 based, while Range<String.Index> is Character based.
Hence you can't just use counts and positions to convert between the two!
In Swift 4, distanceTo() is deprecated. You may have to convert String to NSString to take advantage of its -[NSString rangeOfString:] method, which returns an NSRange.
Swift 4 Complete Solution:
OffsetIndexableCollection (String using Int Index)
https://github.com/frogcjn/OffsetIndexableCollection-String-Int-Indexable-
let a = "01234"
print(a[0]) // 0
print(a[0...4]) // 01234
print(a[...]) // 01234
print(a[..<2]) // 01
print(a[...2]) // 012
print(a[2...]) // 234
print(a[2...3]) // 23
print(a[2...2]) // 2
if let number = a.index(of: "1") {
print(number) // 1
print(a[number...]) // 1234
}
if let number = a.index(where: { $0 > "1" }) {
print(number) // 2
}
You can use this function and call it when ever you need convertion
extension String
{
func CnvIdxTooIntFnc(IdxPsgVal: Index) -> Int
{
return startIndex.distanceTo(IdxPsgVal)
}
}

Resources