Reputation: 5958
JavaScript
for (var x = 0; x < 360; x += 0.5)
{
// ...
}
How do I do this in Kotlin?
Note that my step size is a floating point and so a regular range won't work:
for (x in 0.0 until 360.0 step 0.5) {
// ...
}
I also need to exclude the ending value, hence why I'm using until
.
I will resort to a while loop for now:
var x = 0.0;
while (x < 360.0) {
// ...
x += 0.5
}
Upvotes: 4
Views: 3033
Reputation: 1009
There isn't a way to do this right now in Kotlin because Kotlin does not have "traditional" for
loops. I believe you're right in choosing a while
loop. In fact, traditional for
loops are just while
loops in disguise:
for (init; condition; post) {
// do something
}
can always be rewritten,
init
while (condition) {
// do something
post
}
with no change in behavior, because the init statement will always execute and the condition will always be checked before the loop runs even once. One thing this construct can't give you is a variable that's only scoped to this block. If you're really after that behavior, the following would work, though it's not very idiomatic.
for (x in generateSequence(0.0) { it + 0.5 }.takeWhile { it < 360.0}) {
println(x)
}
If you're using a Sequence, you might also be interested in the more idiomatic forEach
:
generateSequence(0.0) { it + 0.5 }.takeWhile { it < 360.0 }.forEach { x ->
// do something
}
Upvotes: 6
Reputation: 422
Kotlin is so flexible that one could hack a custom solution:
private infix fun (((Double) -> Unit, Double) -> Unit).step(step: Double) =
fun(action: (Double) -> Unit) = this(action, step)
private infix fun Double.upto(to: Double) =
fun(action: (Double) -> Unit, step: Double) {
var v = this
while (v < to) {
action(v)
v += step
}
}
fun main() {
// Usage:
(0.0 upto 360.0 step 0.5) {
println(it)
}
}
What I did above is to create two infix functions.
The upto()
infix function can be used with two Double
s: it takes 0.0 upto 360.0
and returns a function that expects two arguments: an action
function and the step
double value.
The step
infix function can be used with functions returned by upto()
combined with a Double
(so f step 0.5
). It returns a function that calls the upto()
function passing the step
value and the user's { ... }
block that gets called for each iteration.
Short and convoluted.
A simpler alternative:
inline fun doubleFor(
from: Double, to: Double, step: Double, action: (Double) -> Unit
) {
var v = from
while (v < to) {
action(v)
v += step
}
}
fun main() {
// Usage:
doubleFor(0.0, 360.0, 0.5) {
println(it)
}
}
A good IDE would show the argument names next to the values making the meaning of the arguments in the usage code obvious.
A third approach can be found at https://stackoverflow.com/a/44332139/2933899 which allows one to write for(x in 0.0 .. 360.0 step 0.5) { println(x) }
with the inconvenience that the top boundary value is included.
Run these at https://pl.kotl.in/ZuR354Fas
Upvotes: 0
Reputation: 3193
I agree with Answer by @AdamYakes.
Since the until
operator is not available for Floating value type, you can not use
it for floating step
value.
However, If you still want to use
for (x in 0.0 until 360.0 step 0.5) {
// use value
}
you can do that as following:
for (x in 0 until 3600 step 5) {
// use (value / 10)
}
Upvotes: 3
Reputation: 6783
As repeated addition is just a shorthand for multiplication you can look at for (x in 0.0 until 360.0 step 0.5)
as "do something for as many times as 0.5
fits in 360
". Therefore it would make sense to express it like this:
val times = (360 / 0.5).toInt()
repeat(times){
}
of cause you can also inline times to
repeat(times = (360 / 0.5).toInt()){
}
The advantage is that you skip the sequence generation. Con -- you lose the access to your counting variable x.
see also https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/repeat.html
Upvotes: 3