【问题标题】:Scala: custom control structures with several code blocksScala:具有多个代码块的自定义控制结构
【发布时间】:2011-01-01 08:43:21
【问题描述】:

是否可以以before { block1 } then { block2 } finally { block3 } 的方式创建具有多个代码块的自定义控制结构?问题仅与糖部分有关 - 我知道通过将三个块传递给方法可以轻松实现该功能,例如 doInSequence(block1, block2, block3)

一个真实的例子。对于我的测试实用程序,我想创建一个这样的结构:

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

编辑

最后我想出了这个解决方案:

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._

谢谢大家。

【问题讨论】:

    标签: scala control-structure


    【解决方案1】:

    一般原则。您当然也可以使用 f 参数。 (请注意,本例中方法的名称没有意义。)

    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
    

    【讨论】:

    • 这太简单了:)。谢谢
    【解决方案2】:

    如果您希望这些块以特定顺序出现,对 Knut Arne Vedaa 答案的更改将起作用:

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

    【讨论】:

      【解决方案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
        }
      }
      

      【讨论】:

        【解决方案4】:

        不可能有“拆分”方法,但你可以模仿它。

        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>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-04
          • 2013-05-28
          • 2011-10-26
          • 1970-01-01
          • 2011-10-28
          • 2016-12-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多