代码之家  ›  专栏  ›  技术社区  ›  peter_pilgrim

如何使scala在repeat-until中控制抽象?

  •  10
  • peter_pilgrim  · 技术社区  · 16 年前

    我是彼得·朝圣者。我看到MartinOdersky在scala中创建了一个控件抽象。然而,我似乎还不能在Intellij IDEA 9中重复它。是IDE吗?

    package demo
    
    class Control {
    
      def repeatLoop ( body: => Unit ) = new Until( body )
    
      class Until( body: => Unit ) {
        def until( cond: => Boolean ) {
          body;
          val value: Boolean = cond;
          println("value="+value)
          if ( value ) repeatLoop(body).until(cond)
          // if  (cond) until(cond)
        }
      }
    
      def doTest2(): Unit = {
        var y: Int = 1
        println("testing ... repeatUntil() control structure")
        repeatLoop {
          println("found y="+y)
          y = y + 1
        }
        { until ( y < 10 ) }
      }
    
    }
    

    错误消息为:

    信息:编译已完成,有1个错误和0个警告
    信息:1个错误
    信息:0个警告
    C:\users\peter\ideaprojects\helloword\src\demo\control.scala
    错误:错误:行(57)错误:控件。this.repeatloop({
    scala.this.predef.println(“found y=”+(y));
    y= y+(1)
    })类型为control.this.until不接受参数
    重复循环{

    在curried函数中,body可以被认为返回一个表达式(y+1的值),但是repeatuntil的声明body参数明确表示可以忽略还是不可以忽略?

    错误是什么意思?

    4 回复  |  直到 12 年前
        1
  •  10
  •   michael.kebe    16 年前

    这里有一个没有 StackOverflowError .

    scala>   class ConditionIsTrueException extends RuntimeException
    defined class ConditionIsTrueException
    
    scala>   def repeat(body: => Unit) = new {
     |     def until(condition: => Boolean) = { 
     |       try {
     |         while(true) {
     |           body
     |           if (condition) throw new ConditionIsTrueException
     |         }   
     |       } catch {
     |         case e: ConditionIsTrueException =>
     |       }   
     |     
     |     }   
     |   }
    repeat: (body: => Unit)java.lang.Object{def until(condition: => Boolean): Unit}
    
    scala> var i = 0              
    i: Int = 0
    
    scala> repeat { println(i); i += 1 } until(i == 3)
    0
    1
    2
    
    scala> repeat { i += 1 } until(i == 100000)       
    
    scala> repeat { i += 1 } until(i == 1000000)
    
    scala> repeat { i += 1 } until(i == 10000000)
    
    scala> repeat { i += 1 } until(i == 100000000)
    
    scala> 
    

    根据杰斯帕和雷克斯克尔的说法,这里有一个没有例外的解决方案。

    def repeat(body: => Unit) = new {
      def until(condition: => Boolean) = { 
        do {
          body
        } while (!condition)
      }   
    }
    
        2
  •  8
  •   oxbow_lakes    16 年前

    您不需要第二对大括号,用法应该是:

    repeatLoop (x) until (cond) //or...
    repeatLoop {x} until {cond}
    

    而不是:

    repeatLoop {x} { until(cond) } //EXTRA PAIR OF BRACES
    

    误差均值 scala认为您正试图调用带有签名的方法,比如:

    def repeatLoop(x: => Unit)(something: X) //2 parameter lists
    

    也找不到这样的方法。这是在说 “repeatloop(body)”不接受参数 . 解决方案的完整代码列表可能看起来更像:

    object Control0 {
      def repeatLoop(body: => Unit) = new Until(body)
    
      class Until(body: => Unit) {
        def until(cond: => Boolean) {
          body;
          val value: Boolean = cond;
    
          if (value) repeatLoop(body).until(cond)
        }
      }
    
    
      def main(args: Array[String]) {
        var y: Int = 1
        println("testing ... repeatUntil() control structure")
        repeatLoop {
          println("found y=" + y)
          y += 1
        }.until(y < 10)
      }
    }
    

    这里有两个有用的观察结果:

    1. 该解决方案不是尾递归的,将导致 StackOverflowError 对于长迭代(尝试 while (y < 10000) )
    2. 这个 until 对我来说似乎是错误的(当情况变为真的时候停止是比较自然的,而不是在情况变为真的时候继续)。
        3
  •  6
  •   Don Mackenzie    16 年前

    一张单人票怎么样 重复直到 .

    def repeat(b: => Unit) = new AnyRef {def until(c: => Boolean) {b; while (! c) b}}
    

    例如,它给出了:

    scala> repeat {
         |   println("i = "+i)
         |   i+=1
         | } until (i >= 10)
    i = 0
    i = 1
    i = 2
    i = 3
    i = 4
    i = 5
    i = 6
    i = 7
    i = 8
    i = 9
    
        4
  •  5
  •   Markus Marvell    12 年前

    如上所述,递归:)

    def repeat(b: => Unit) = new {def until(c: => Boolean) = { b; if (c) until(c) }}
    
    var i = 0
    repeat {
      println(i)
      i+=1
    } until (i < 10)
    

    @tailrec也进行了优化。

    爱斯卡拉:)

    推荐文章