Ranges

range 表达式是通过 rangeTo 函数形成的。rangeTo 函数拥有形如 .. 的操作符,该操作符是用 in 和 !in 实现的。 Range 可以对任何可比较的类型做操作,但对整数基本类型是优化过的。下面是些例子:

  1. if(i in1..10){
  2. println(i)
  3. }
  4. if(x !in1.0..3.0) println(x)
  5. if(str in"island".."isle") println(str)

数字的范围有个附加的特性:它们可以迭代。编译器会把它转成类似于 java 的 for 循环的形式,且不用担心越界:

  1. for(i in1..4)print(i)// prints "1234"
  2. for(i in4..1)print(i)// prints nothing
  3. for(x in1.0..2.0)print("$x ")// prints "1.0 2.0 "

如果你想迭代数字并想反过来,这个相当简单,你可以使用 downTo() 函数

  1. for(i in4 downTo 1)print(i)

也可以使用指定步数的迭代,这个用到 step()

  1. for(i in1..4 step 2)print(i)// prints "13"
  2. for(i in4 downTo 1 step 2)print(i)// prints "42"
  3. for(i in1.0..2.0 step 0.3)print("$i ")// prints "1.0 1.3 1.6 1.9 "

工作原理

在标准库中有俩种接口:Range 和 Progression

Range 表示数学范围上的一个间隔。它有俩个端点:start 和 end 。主要的操作符是 contains 通常在 in/!in 操作符内:

Progression 表示一个算数级数。它有一个 start 和 end 以及一个非零 increment 。Progression 是Iterable 的一个子类,因此可以使用在 for 循环中,或者 map filter 等等。第一个元素是 start 下一个元素都是前一个元素的 increment 。Progression 的迭代与 java/javaScript 的 for 循环相同:

  1. // if increment > 0
  2. for(int i = start; i <=end; i += increment){
  3. // ...
  4. }
  5. // if increment < 0
  6. for(int i = start; i >=end; i += increment){
  7. // ...
  8. }

范围指标

使用例子:

  1. // Checking if value of comparable is in range. Optimized for number primitives.
  2. if(i in1..10) println(i)
  3. if(x in1.0..3.0) println(x)
  4. if(str in"island".."isle") println(str)
  5. // Iterating over arithmetical progression of numbers. Optimized for number primitives (as indexed for-loop in Java).
  6. for(i in1..4)print(i)// prints "1234"
  7. for(i in4..1)print(i)// prints nothing
  8. for(i in4 downTo 1)print(i)// prints "4321"
  9. for(i in1..4 step 2)print(i)// prints "13"
  10. for(i in(1..4).reversed())print(i)// prints "4321"
  11. for(i in(1..4).reversed() step 2)print(i)// prints "42"
  12. for(i in4 downTo 1 step 2)print(i)// prints "42"
  13. for(x in1.0..2.0)print("$x ")// prints "1.0 2.0 "
  14. for(x in1.0..2.0 step 0.3)print("$x ")// prints "1.0 1.3 1.6 1.9 "
  15. for(x in2.0 downTo 1.0 step 0.3)print("$x ")// prints "2.0 1.7 1.4 1.1 "
  16. for(str in"island".."isle") println(str)// error: string range cannot be iterated over

常见的接口的定义

有俩种基本接口:RangeProgression

Range 接口定义了一个范围,或者是数学意义上的一个间隔。

  1. interfaceRange<T :Comparable<T>>{
  2. val start: T
  3. val end: T
  4. fun contains(Element: T):Boolean
  5. }

Progression 定义了数学上的级数。包括 start end increment 端点。最大的特点就是它可以迭代,因此它是 Iterable 的子类。end 不是必须的。

  1. interfaceProgression<N :Number>:Iterable<N>{
  2. val start : N
  3. val end: N
  4. val increment :Number
  5. }

与 java 的 for 循环类似:

  1. // if increment > 0
  2. for(int i = start; i <=end; i += increment){
  3. // ...
  4. }
  5. // if increment < 0
  6. for(int i = start; i >=end; i += increment){
  7. // ...
  8. }

类的实现

为避免不需要的重复,让我们先考虑一个数字类型 Int 。其它的数字类型也一样。注意这些类的实例需要用相应的构造函数来创建,使用 rangeTo() downTo() reversed() stop() 实用函数。

IntProgression 类很直接也很简单:

  1. classIntProgression(override val start:Int,override val end:Int,override val increment:Int):Progression<Int>{
  2. override fun iterator():Iterator<Int>=IntProgressionIteratorImpl(start,end, increment)
  3. }

IntRange 有些狡猾:它实现了 Progression<Int>Range<Int> 接口,因为它天生以通过 range 迭代(默认增加值是 1 ):

  1. classIntRange(override val start:Int,override val end:Int):Range<Int>,Progression<Int>{
  2. override val increment:Int
  3. get()=1
  4. override fun contains(element:Int):Boolean= start <= element && element <=end
  5. override fun iterator():Iterator<Int>=IntProgressionIteratorImpl(start,end, increment)
  6. }

ComparableRange 也很简单:

  1. classComparableRange<T :Comparable<T>>(override val start: T,override val end: T):Range<T>{
  2. override fun contains(element: T):Boolean= start <= element && element <=end
  3. }

一些实用的函数

rangeTo()

rangeTo() 函数仅仅是调用 *Range 的构造函数,比如:

  1. classInt{
  2. fun rangeTo(other:Byte):IntRange=IntRange(this,Other)
  3. fun rangeTo(other:Int):IntRange=IntRange(this, other)
  4. }

downTo()

downTo() 扩展函数可以为任何数字类型定义,这里有俩个例子:

  1. fun Long.downTo(other:Double):DoubleProgression{
  2. returnDoubleProgression(this, other,-1.0)
  3. }
  4. fun Byte.downTo(other:Int):IntProgression{
  5. returnIntProgression(this, other,-1)
  6. }

reversed()

reversed() 扩展函数是给所有的 *Range*Progression 类定义的,并且它们都返回反向的级数。

  1. fun IntProgression.reversed():IntProgression{
  2. returnIntProgression(end, start,-increment)
  3. }
  4. fun IntRange.reversed():IntProgression{
  5. returnIntProgression(end, start,-1)
  6. }

step()

step() 扩展函数是给所有的 *Range*Progression 类定义的,所有的返回级数都修改了 step 值。注意 step 值总是正的,否则函数不会改变迭代的方向。

  1. fun IntProgression.step(step:Int):IntProgression{
  2. if(step <=0)throwIllegalArgumentException("Step must be positive, was: $step")
  3. returnIntProgression(start,end,if(increment >0) step else-step)
  4. }
  5. fun IntRange.step(step:Int):IntProgression{
  6. if(step <=0)throwIllegalArgumentException("Step must be positive, was: $step")
  7. returnIntProgression(start,end, step)
  8. }