Incrementing the for loop (loop variable) in scala by power of 5 -
i had asked question on javaranch, couldn't response there. posting here well:
i have particular requirement increment in loop variable done multiplying 5 after each iteration. in java implement way:
for(int i=1;i<100;i=i*5){}
in scala trying following code-
var j=1 for(i<-1.to(100).by(scala.math.pow(5,j).toint)) { println(i+" "+j) j=j+1 }
but printing following output: 1 1 6 2 11 3 16 4 21 5 26 6 31 7 36 8 .... ....
its incrementing 5 always. how got multiplying increment 5 instead of adding it.
let's first explain problem. code:
var j=1 for(i<-1.to(100).by(scala.math.pow(5,j).toint)) { println(i+" "+j) j=j+1 }
is equivalent this:
var j = 1 val range: range = predef.intwrapper(1).to(100) val increment: int = scala.math.pow(5, j).toint val byrange: range = range.by(increment) byrange.foreach { println(i+" "+j) j=j+1 }
so, time mutate j
, increment
, byrange
have been computed. , range
immutable object -- can't change it. if produced new ranges while did foreach
, object doing foreach
still same.
now, solution. put, range
not adequate needs. want geometric progression, not arithmetic one. me (and pretty else answering, seems), natural solution use stream
or iterator
created iterate
, computes next value based on previous one.
for(i <- iterator.iterate(1)(_ * 5) takewhile (_ < 100)) { println(i) }
edit: stream vs iterator
stream
, iterator
different data structures, share property of being non-strict. property enables iterate
exist, since method creating infinite collection1, takewhile
create new2 collection finite. let's see here:
val s1 = stream.iterate(1)(_ * 5) // s1 infinite val s2 = s1.takewhile(_ < 100) // s2 finite val i1 = iterator.iterate(1)(_ * 5) // i1 infinite val i2 = i1.takewhile(_ < 100) // i2 finite
these infinite collections possible because collection not pre-computed. on list
, elements inside list stored somewhere time list has been created. on above examples, however, first element of each collection known in advance. others computed if , when required.
as mentioned, though, these different collections in other respects. stream
immutable
data structure. instance, can print contents of s2
many times wish, , show same output every time. on other hand, iterator
mutable data structure. once used value, value forever gone. print contents of i2
twice, , empty second time around:
scala> s2 foreach println 1 5 25 scala> s2 foreach println 1 5 25 scala> i2 foreach println 1 5 25 scala> i2 foreach println scala>
stream
, on other hand, lazy
collection. once value has been computed, stay computed, instead of being discarded or recomputed every time. see below 1 example of behavior in action:
scala> val s2 = s1.takewhile(_ < 100) // s2 finite s2: scala.collection.immutable.stream[int] = stream(1, ?) scala> println(s2) stream(1, ?) scala> s2 foreach println 1 5 25 scala> println(s2) stream(1, 5, 25)
so stream
can fill memory if 1 not careful, whereas iterator
occupies constant space. on other hand, 1 can surprised iterator
, because of side effects.
(1) matter of fact, iterator
not collection @ all, though shares lot of methods provided collections. on other hand, problem description gave, not interested in having collection of numbers, in iterating through them.
(2) actually, though takewhile
create new iterator
on scala 2.8.0, new iterator still linked old one, , changes in 1 have side effects on other. subject discussion, , might end being independent in future.
Comments
Post a Comment