10

我是彼得朝圣者。我看到 Martin Odersky 在 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) 错误:Control.this。类型 Control.this.Until 的repeatLoop({
scala.this.Predef.println("found y=".+(y));
y = y.+(1)
}) 不带参数
repeatLoop {

在 curried 函数中,可以认为主体返回一个表达式(y+1 的值),但是 repeatUntil 的声明主体参数清楚地表明这可以忽略还是不可以?

错误是什么意思?

4

4 回答 4

10

这是一个没有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> 

根据 Jesper 和 Rex Kerr 的说法,这里是一个没有异常的解决方案。

def repeat(body: => Unit) = new {
  def until(condition: => Boolean) = { 
    do {
      body
    } while (!condition)
  }   
}
于 2010-06-14T11:26:14.733 回答
8

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

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对我来说似乎是错误的方式(当条件为真时停止会更自然,而不是在它为真时继续)。
于 2010-06-14T09:18:48.907 回答
6

一个衬垫如何重复直到

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
于 2010-06-14T16:21:26.073 回答
5

如上所述但递归:)

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 优化的。

爱斯卡拉:)

于 2013-11-12T19:47:03.597 回答