2011-01-01 11 views
6

Có thể tạo cấu trúc điều khiển tùy chỉnh với một số khối mã, theo kiểu before { block1 } then { block2 } finally { block3 } không? Câu hỏi là về phần đường chỉ - tôi biết các chức năng có thể dễ dàng đạt được bằng cách đi qua ba khối để một phương pháp, như doInSequence(block1, block2, block3).Scala: cấu trúc điều khiển tùy chỉnh với một số khối mã

Ví dụ thực tế về cuộc sống. Đối với các tiện ích thử nghiệm của tôi, tôi muốn tạo một cấu trúc như thế này:

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

EDIT:

Cuối cùng tôi đã đưa ra giải pháp này:

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

Đầu ra là:

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

Chủ yếu dựa trên câu trả lời bằng Thomas Lockney, tôi vừa thêm đối tượng đồng hành để có thể import MyTimer._

Cảm ơn tất cả các bạn.

Trả lời

3

Ví dụ đã cho, khóa sẽ là loại trả về là getTime có phương thức after trên đó. Tùy thuộc vào ngữ cảnh, bạn có thể sử dụng một lớp đơn hoặc đặc điểm kết thúc tốt đẹp cả hai phương thức. Dưới đây là một ví dụ rất đơn giản về cách bạn có thể tiếp cận:

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

Nguyên tắc chung. Tất nhiên bạn có thể có tham số f. (. Lưu ý rằng tên của các phương pháp không có ý nghĩa trong ví dụ này)

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

Thật đáng xấu hổ :). Cảm ơn –

8

Nếu bạn muốn những khối để xuất hiện theo thứ tự cụ thể, sự thay đổi này để trả lời Knut Arne Vedaa của sẽ làm việc:

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

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

... 
1

Không thể có phương pháp "tách", nhưng bạn có thể mô phỏng nó.

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>