如何使 Scala 控制重复直到抽象?

发布于 2024-09-05 04:22:57 字数 1083 浏览 4 评论 0原文

我是彼得·皮尔格林。我看到 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.repeatLoop({
scala.this.Predef.println("找到 y=".+(y));
y = y.+(1)
Control.this.Until 类型的 }) 不带参数
重复循环 {

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

错误是什么意思?

I am Peter Pilgrim. I watched Martin Odersky create a control abstraction in Scala. However I can not yet seem to repeat it inside IntelliJ IDEA 9. Is it the 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 ) }
  }

}

The error message reads:

Information:Compilation completed with 1 error and 0 warnings
Information:1 error
Information:0 warnings
C:\Users\Peter\IdeaProjects\HelloWord\src\demo\Control.scala
Error:Error:line (57)error: Control.this.repeatLoop({
scala.this.Predef.println("found y=".+(y));
y = y.+(1)
}) of type Control.this.Until does not take parameters
repeatLoop {

In the curried function the body can be thought to return an expression (the value of y+1) however the declaration body parameter of repeatUntil clearly says this can be ignored or not?

What does the error mean?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

极致的悲 2024-09-12 04:22:57

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

Here is a solution without the 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> 

According to Jesper and Rex Kerr here is a solution without the Exception.

def repeat(body: => Unit) = new {
  def until(condition: => Boolean) = { 
    do {
      body
    } while (!condition)
  }   
}
画尸师 2024-09-12 04:22:57

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

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(尝试 < code>while (y < 10000))
  2. until 对我来说似乎是错误的方式(当条件成立时停止会更自然,而不是在条件成立时继续真的)。

You don't need the 2nd pair of braces, the usage should be:

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

And not:

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

The error means that Scala thinks you are trying to call a method with a signature something like:

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

And can find no such method. It is saying "repeatLoop(body)" does not take parameters. A full code listing for the solution probably looks something a bit more like:

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)
  }
}

There are two useful observations to make here:

  1. The solution is not tail-recursive and will result in a StackOverflowError for long iterations (try while (y < 10000))
  2. The until seems the wrong way round to me (it would be more natural to stop when the condition becomes true, not carry on while it is true).
放手` 2024-09-12 04:22:57

一个单行重复直到怎么样?

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

How about a one liner for repeat until.

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

Which, for example, gives:-

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
旧情勿念 2024-09-12 04:22:57

如上所述,但递归:)

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

爱斯卡拉:)

As above yet recursive :)

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)

It's @tailrec optimized too.

Llove scala :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文