Scala: customizable control structures with multiple blocks of code

Is it possible to create a custom control structure with several blocks of code, in the order before { block1 } then { block2 } finally { block3 } ? The only question is sugar - I know that functionality can be easily achieved by passing three blocks to a method, for example doInSequence(block1, block2, block3) .

Real life example. For my testing utilities, I would like to create a structure like this:

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

EDIT

Finally, I came up with this solution:

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

Output:

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

Basically, based on Thomas Lockney's answer, I just added a companion object to be able to import MyTimer._

Thanks guys.

+6
scala control-structure
source share
4 answers

In this example, the key should have a return type getTime on it after . Depending on the context, you can use one class or attribute that combines both methods. Here is a very simplified example of how you could work with it:

 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 } } 
+3
source share

General principle. Of course, you can take the parameters. (Note that the method name does not make sense in this example.)

 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 = Foo@1f16e6e 
+13
source share

If you want these blocks to be displayed in a specific order, this is a change to Knut Arne Veda's answer:

 class Foo1 { def before(f: => Unit) = { f; new Foo2 } } class Foo2 { def then(f: => Unit) = { f; new Foo3 } } ... 
+8
source share

It is not possible to have a split method, but you can emulate it.

 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> 
+1
source share

All Articles