2010-06-14 17 views
10

我是Peter Pilgrim。我看到Martin Odersky在Scala中創建了一個控制抽象。不過,我似乎還不能在IntelliJ IDEA 9中重複它。它是IDE嗎?一個人如何讓Scala控制抽象重複直到?

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

} 

錯誤消息讀取:

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 {

在咖喱函數主體可以被認爲以返回一個表達式(y的值+ 1)然而repeatUntil的聲明機體參數明確地說,這可以忽略不計?

錯誤是什麼意思?

回答

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的說法,這裏是一個沒有Exception的解決方案。

def repeat(body: => Unit) = new { 
    def until(condition: => Boolean) = { 
    do { 
     body 
    } while (!condition) 
    } 
} 
+0

不錯。我喜歡匿名函數對象。 – 2010-06-14 12:18:25

+1

它被稱爲結構類型 – 2010-06-14 13:38:31

+4

爲什麼嘗試/抓住,當你可以'做{body} while(!condition)'? – 2010-06-14 14:44:57

8

你不需要第二對大括號,用法應該是:

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

而不是:

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

的錯誤意味着是斯卡拉認爲你試圖調用一種簽名方法如下:

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似乎是對我來說錯誤的方式(當條件成立時停止會更自然,而不是繼續,而不是繼續)。
+0

啊我明白了。非常感謝。代碼更改確實有效 1.需要採取的步驟 2.這是Martin的Odersky練習。是的,你用''whileLoop(body:=> Boolean)''來寫另一種方式控制抽象更容易。我認爲你可以更容易地進行尾部遞歸。 我試圖複製「重複」...「直到」結構,因此我不想在「repeatLoop」函數類型和「until」函數對象方法之間加上額外的(「。」)。 如果您嘗試此操作,則會出現編譯錯誤:直到找不到值。 – 2010-06-14 10:17:51

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 
4

如上又遞歸:)

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優化過。

Llove scala :)

+0

難道你忘記了直到def的返回類型嗎? – Bas 2013-11-15 13:39:07

+0

哎呀,謝謝。你就像編譯器:) – 2013-11-18 07:03:02

相關問題