2011-01-01 12 views
6

複数のコードブロックを持つカスタムコントロール構造をbefore { block1 } then { block2 } finally { block3 }の形式で作成できますか?問題は糖部分についてだけです - 私は機能が簡単に方法に3ブロックを渡すことによって達成できることを知っていますdoInSequence(block1, block2, block3)のような。複数のコードブロックを持つカスタムコントロール構造

実生活の例です。私はこのような構造体を作成したいのですが、私のテストユーティリティについて:

getTime(1000) { 
    // Stuff I want to repeat 1000 times. 
} after { (n, t) => 
    println("Average time: " + t/n) 
} 

EDIT

最後に、私はこの解決策を考え出した:

object MyTimer { 
    def getTime(count: Int)(action : => Unit): MyTimer = { 
    val start = System.currentTimeMillis() 
    for(i <- 1 to count) { action } 
    val time = System.currentTimeMillis() - start 
    new MyTimer(count, time) 
    } 
} 

class MyTimer(val count: Int, val time: Long) { 
    def after(action: (Int, Long) => Unit) = { 
    action(count, time) 
    } 
} 

// Test 
import MyTimer._ 

var i = 1 
getTime(100) { 
    println(i) 
    i += 1 
    Thread.sleep(10) 
} after { (n, t) => 
    println("Average time: " + t.toDouble/n) 
} 

出力は次のとおりです。

1 
2 
3 
... 
99 
100 
Average time: 10.23 

ほとんどの回答に基づいてThomas Lockney、私はちょうどできるようにコンパニオンオブジェクトを追加しましたimport MyTimer._

ありがとう、皆さん。

答えて

3

たとえば、getTimeの戻り値の型にafterメソッドがあることが重要です。コンテキストに応じて、両方のメソッドをまとめた単一のクラスまたは特性を使用できます。ここにあなたがどのようにアプローチするかの非常に簡単な例があります:

class Example() { 
    def getTime(x: Int)(f : => Unit): Example = { 
    for(i <- 0 to x) { 
     // do some stuff 
     f 
     // do some more stuff 
    } 
    // calculate your average 
    this 
    } 
    def after(f: (Int, Double) => Unit) = { 
    // do more stuff 
    } 
} 
13

一般原則。もちろん、パラメータを取ることもできます。あなたはこれらのブロックは、特定の順序で表示させたい場合(メソッドの名前は、この例では意味を持たないことに注意してください)

scala> class Foo { 
    | def before(f: => Unit) = { f; this } 
    | def then(f: => Unit) = { f; this } 
    | def after(f: => Unit) = { f; this } 
    | } 
defined class Foo 

scala> object Foo { def apply() = new Foo } 
defined module Foo 

scala> Foo() before { println("before...") } then { 
    | println("then...") } after { 
    | println("after...") } 
before... 
then... 
after... 
res12: Foo = [email protected] 
+0

これは恥ずかしいほど簡単です:)。ありがとう –

8

、クヌートアルネVedaaの答えに、この変更は動作します:

class Foo1 { 
    def before(f: => Unit) = { f; new Foo2 } 
} 

class Foo2 { 
    def then(f: => Unit) = { f; new Foo3 } 
} 

... 
1

「分割」方法は使用できませんが、エミュレートすることはできます。

class Finally(b: => Unit, t: => Unit) { 
    def `finally`(f: => Unit) = { 
     b 
     try { t } finally { f } 
    } 
} 

class Then(b: => Unit) { 
    def `then`(t: => Unit): Finally = new Finally(b, t) 
} 

def before(b: => Unit): Then = new Then(b) 

scala> before { println("Before") } `then` { 2/0 } `finally` { println("finally") } 
Before 
finally 
[line4.apply$mcV$sp] (<console>:9) 
(access lastException for the full trace) 
scala> 
関連する問題