Kotlin line break in sums — result depends on operator placement - kotlin

today I've encountered a strange behaviour in Kotlin that I cannot explain. Given the following code:
data class Data(
val v1: Int,
val v2: Int,
val v3: Int)
fun main() {
val d = Data(1,1,1)
val sum1 = d.v1 + d.v2 + d.v3
println("Oneliner: $sum1") // prints: Oneliner: 3
val sum2 = d.v1
+ d.v2
+ d.v3
println("OperatorFirst: $sum2") // prints: OperatorFirst: 1
val sum3 = d.v1 +
d.v2 +
d.v3
println("OperatorLast: $sum3") // prints: OperatorLast: 3
}
(Testable at: https://pl.kotl.in/gMjif_6FO)
Now it seems to depend on where you place the + operator to get the correct result of 3. However, the IDE doesn't show that anything might be wrong with the second version and i couldn't find any information of why this case would behave differently.
A question on the software engineering space also says that several coding guidelines suggest to put the operator at the beginning of the line: https://softwareengineering.stackexchange.com/questions/93670/line-break-before-after-operator
Also, the only explanation I could find for this behaviour is that the + at the line beginnings is interpreted as a unary plus operator. https://www.programiz.com/kotlin-programming/operators#unary
However, even this makes no sense to me on a val

That's the price you pay for optional semicolons. Andrey Breslav said in one of his lectures that it is intended behavior. Binary operators like + or * should be placed on the top line, not the bottom line. If you want to place them on bottom line, use parentheses:
val sum = (1
+ 1
+ 1)
println(sum) // prints: 3

Related

When should you use plus, minus, times functions instead of using the operators in Kotlin?

I cannot think of a case where using the Kotlin built-in plus, minus, times etc. functions would return a different result from just using the corresponding operators (+, -, *). Why would you ever want to use these functions in your Kotlin code?
Just in case you aren't aware, these are operator overloads. The named functions are how the operators' functionality is defined.
There is a case for using the named versions. The function calls don't pay attention to operator precedence and are evaluated sequentially if you chain them.
val x = 1
val y = 2
val z = 3
println(x + y * z) // equivalent to 1 + (2 * 3) -> 7
println(x.plus(y).times(z)) // equivalent to (1 + 2) * 3 -> 9
This could be clearer than using the operators if you have a lot of nested parentheses, depending on the context of the type of math you're doing.
result = ((x - 7) * y - z) * 10
// vs
result = x.minus(7).times(y).minus(z).times(10)
It's not really applicable for basic algebra like this, but you might have classes with operator overloads where the logic can be more easily reasoned through with the sequential approach.
By explicitly stating function names you can perform a safe call on a nullable number which cannot be done with an operator.
For example:
fun doubleOrZero(num: Int?) : Int {
return num?.times(2) ?: 0
}

kotlin rem operator doesn't give me correct answer

I use remainder inside my code with kotlin in android project but with this value I don't get the correct answer.
variable is :
val vv = 1529.71
val ratio = 0.01
val remainder = vv.rem(ratio)
it's must be zero but remainder value is :
4.5363018896793506E-15
I don't understand why this happened.
The answer is because vv isn't actually 1529.71 but the closest possible Double, the exact value is 1529.7100000000000363797880709171295166015625 (the easiest way to see it is println(java.math.BigDecimal(vv))). If you want to represent decimal numbers exactly, use BigDecimal and pass the fraction as a string:
val vv = BigDecimal("1529.71")
val ratio = BigDecimal("0.01")
val remainder = vv.rem(ratio)
Read more about floating point here: https://floating-point-gui.de/
In my case, i had to get only the exact digits of two numbers after the decimal point.
I achieved it by doing this:
val input = 30.47f
val remainder = (input * 100).toInt() - (input.toInt() * 100)
// remainder = 47 exactly, and not 469999999...
Hope this would be helpful for someone.

how to autogenerate array in kotlin similar to numpy?

hello let me do a demonstration in python about what I want to achieve in kotlin:
np.linspace(start = 0, stop = 100, num = 5)
This results:
-------------------------
|0 | 25 | 50 | 75 | 100 |
-------------------------
Now in Kotlin how can I get the same result? Is there a similar library?
This should work exactly like linspace (not handling cases when num is 0 or 1):
fun linspace(start: Int, stop: Int, num: Int) = (start..stop step (stop - start) / (num - 1)).toList()
It makes use of the rangestart..stop (a range in kotlin is inclusive) and the function step lets us define how far the steps in this ranges should be.
EDIT
As #forpas suggested in the comments the step should be calculated using (stop - start) and not only stop. Using stop alone would only work if the start was 0.
#Alexey Romanov correctly said that unless you explicitly need a List as return type you should return the IntProgression (it does not hold all the elements in memory like a list does) since its also Iterable.
Thank you both for your input!
Not exactly the same, but it generates an array with 5 integers, multiples of 25 starting from 0:
val array = Array(5) { it * 25 }
the result is:
[0, 25, 50, 75, 100]
You can create a function simulating what you need:
fun linspace(start: Int, stop: Int, num: Int) = Array(num) { start + it * ((stop - start) / (num - 1)) }
DoubleProgression used to exist but was removed, because it raises rounding issues; you can copy the sources from that commit as a starting point if you really need it. Or consider converting it to a BigDecimalProgression instead. Of course, you need division to get the step from your arguments, which isn't exact even for BigDecimal.
You can also use sequences:
fun linspaceD(start: Double, stop: Double, num: Double): Sequence<Double> {
val step = (stop - start) / (num - 1)
return sequence {
for i in 0 until num yield(start + step*i)
}
}
Note that this resolves rounding in a specific way, by always yielding num values even if the last one is slightly greater than stop.

Kotlin is ignoring expression

I'm wondering why the below code generates the strange results, and compiler doesn't show any error or warning. This looks like an extremely efficient source of bugs.
val a = 10 * 20 +
10 * 30
val b = 10 * 20
+ 10 * 30
val c = (
(10 * 20)
+ (10 * 30)
)
val d = (10 * 20)
+ (10 * 30)
println(a)
println(b)
println(c)
println(d)
And the output is:
500
200
500
200
Kotlin has optional semicolons, it allows and encourages source code to omit a statement separator (i.e. semicolon ;). As a result, it can get hard for the compiler to guess what you, as a programmer, actually intend to do:
val b = 10 * 20
+ 10 * 30
Will be compiled to an assignment of b = 500 and a second statement that results in 300 but never gets assigned to anything (same with d). How would you consider the compiler to know that the second line is actually part of the first expression? It's valid on its own.
This thread gives further details.
I looks like I was lucky to use an operator which also has unary version +.
The problem is that Kotlin allows for a kind of expressions which do nothing in fact like this:
12345
I can also have:
- 12345
which is just a negative number. I can also have positive number:
+ 12345
So in this case:
val a = 20 +
30
I have one expression, as the + requires another argument, which can be found in the next line.
However here I have two expressions
val a = 20
+ 30
The variable a will have value 20 and the second expression will do nothing.
However there is no unary version of *, so this works:
val a = 10 *
20
and a == 200, and this makes a compilation error:
val a = 10
* 20
Error:(397, 17) Kotlin: Expecting an element
Adding semicolons doesn't change anything, as the last expression is still not valid, and causes the compilation error.
And you can always use brackets:
val x = (10
+ 20)

Syntax errors in sml: Inserting LOCAL

The following method determines how many numbers can be added up starting from the beginning of the list without adding up to 4:
number_before_Reaching_sum (4, [1,2,3,4,6]);
should return : val it = 2 : int
fun number_before_reaching_sum (sum : int * int list) =
let val len_orig_list = length (#2 sum)
in fun num_bef_reach_sum (sum) =
if #1 sum <= 0
then len_orig_list - (length (#2 sum)) - 1
else num_bef_reach_sum (#1 sum - hd (#2 sum), tl (#2 sum))
end
syntax error: inserting LOCAL
syntax error found at EOF
I can't seem to find the errors in this code. I have some experience with Python, but just starting to learn sml. I'm loving it, but I don't understand all the error messages. I have really spent hours on this, but I think I don't know enough to solve my problem. I tried exchanging let with local, but i still got a syntax error (equalop). I think that the function between in and end is an expression and not a declaration. But I would appreciate any comments on this. If you come up with alternative code, it would be great if you did it without using more advanced features, since I'm just trying to get the basics down :-)
You probably meant this:
fun number_before_reaching_sum (sum : int * int list) =
let
val len_orig_list = length (#2 sum)
fun num_bef_reach_sum (sum) =
if #1 sum <= 0
then len_orig_list - (length (#2 sum)) - 1
else num_bef_reach_sum (#1 sum - hd (#2 sum), tl (#2 sum))
in
num_bef_reach_sum (sum)
end
With let … in … end, the part between let and in is for the local definitions; the part between in and end is for the expression which will be the evaluation of the let … in … end expression (this construct is indeed an expression).
Think of let … in … end as a possibly complex expression. You hoist parts of the expression as definitions, then rewrite the complex expression using references to these definitions. This help write shorter expressions by folding some of its sub‑expressions. This construct is also required when recursion is needed (a recursion requires a defining name).
Another way to understand it, is as the application of an anonymous function whose arguments bindings are these definitions.
Ex.
let
val x = 1
val y = 2
in
x + y
end
is the same as writing
(fn (x, y) => x + y) (1, 2)
which is the same as writing
1 + 2
You erroneously put a definition at the place of the expression the whole evaluates to.
(note I did not check the function's logic, as the question was about syntax)