Scala问题自定义控件结构< - >输入参数

时间:2010-11-03 15:46:57

标签: generics scala

我不明白如何正确地在Scala中应用泛型类型。我设法实现了自己的控制结构(“除非”,“ForEach”),但目前它们仅限于“Int”类型......有谁知道如何更改适用于泛型类型的实现?!

实现对我来说无关紧要,但我真的想保持现在的控制结构:

import Controls._ 

val Cond = false
val Elements = List(1,2,3)

Unless(Cond) {
  var sum = 0
  ForEach {
    sum += Element 
  } In(Elements) 
  println("The Sum: " + sum)
}

我试了好几个小时,但我不知道类型参数问题的解决方案。这是我的“Int”有限实现:

object Controls {

  def Unless(cond: => Boolean)(block: => Unit) = {
    if(!cond) block
  }

  var current = 0
  def ForEach(block: => Unit) = {
    new {
      def In(list:List[Int]) = {
        list foreach { i =>
          current = i
          block
        }
      }
    }
  }

  def Element = current

}

任何提示都非常受欢迎,因为我现在真的被困住了......

2 个答案:

答案 0 :(得分:4)

基本上,您希望在Unless块参数中注入一个定义:

Unless
(Cond)
{ // you want Element available here
  var sum = 0
  ForEach {
    sum += Element 
  } In(Elements) 
  println("The Sum: " + sum)
}

您不能在外面定义它,因为它会提前修复类型。所以我会给你两个解决方案。首先,将某些内容注入块中的传统方法是将其作为参数传递:

Unless(Cond) {
  var sum = 0
  ForEach { Element =>
    sum += Element 
  } In(Elements) 
  println("The Sum: " + sum)
}

您将无法获得单独使用的代码,因为编译器无法推断出Element的类型。因此,需要进行以下两种更改:

  ForEach[int] { Element =>
  ForEach { Element: Int =>

该代码如下所示:

object Controls {
  def Unless(cond: => Boolean)(block: => Unit) = {
    if(!cond) block
  }

  def ForEach[T](block: T => Unit) = {
    new {
      def In(list:List[T]) = {
        list foreach block
      }
    }
  }
}

另一个解决方案是创建一个特定于类型的控件的工厂,如下所示:

object Controls {
  def apply[T] = new Controls[T]

  class Controls[T] {
    def Unless(cond: => Boolean)(block: => Unit) = {
      if(!cond) block
    }

    private var current: T = _
    def Element = current
    def ForEach(block: => Unit) = {
      new {
        def In(list:List[T]) = {
          list foreach { i =>
            current = i
            block
          }
        }
      }
    }
  }
}

然后你就这样使用它:

val controls = Controls[Int]; import controls._

其余的就像你的例子一样。

答案 1 :(得分:1)

def ForEach[T](block: => Unit): T = {
    var current: T = _
    new {
        def In(list: List[T]) = {
            list foreach { i =>
                current = i
                block
            }
        }
    }
    current
}

应该做的伎俩。

编辑:当您在ForEach方法之后使用current时,您可能希望更改ForEach以返回current。我编辑了代码段以反映这一点。