开发者

Scala problem custom control structures <-> Type parameters

I don´t understand how to apply generic types in Scala correctly. I´ve managed to implement my own control structures ("unless", "ForEach"), but they are limited to "Int" types at the moment... Does anyone know how to change that implementation that works for generic types?!

The implementation doesn´t matter that much for me, but I really want to keep the control structures as they are now:

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

I tried it for hours, but I don´t know a solution for the problem with the type parameters. Here´s my "Int" limited implementation:

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 =>
          curre开发者_运维知识库nt = i
          block
        }
      }
    }
  }

  def Element = current

}

Any hint´s are very welcome as I´am really stuck right now...


Basically, you want to inject a definition inside the Unless block parameter:

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

You can't define it outside, because it would fix the type ahead of time. So I'll give you two solutions. First, the traditional way of injecting something into a block is by passing it as a paramter:

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

You won't be able to get a code that works like that alone, because there is NOTHING available for the compiler to infer the type of Element. So either of these two changes would be needed:

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

The code for that would look like this:

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

The other solution is to make a factory of type-specific controls, like this:

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

Then you use it like this:

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

And the rest works just as in your example.


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

Should do the trick.

EDIT: And seeing as you use current after the ForEach method, you may want to change ForEach to return current. I edited the code snippet to reflect this.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜