0

针对我的问题如何开发宏以短路空值?有人向我指出了一个早期的长线程,其中有很多答案,其中最引人注目的是https://stackoverflow.com/a/5569905。但它不适用于像 Int 这样的 Scala AnyVal“原语”:

object TestOp {

  class SafeDereference[A](obj: A) {
    def ?[B >: Null](function: A => B): B = if (obj == null) null else function(obj)
  }
  implicit def safeDereference[A](obj: A) = new SafeDereference(obj)

  class C { 
    def getValue: Int = 0                     
  }

  def main(args: Array[String]) {
    val c = new C
    val x:Int = c ? (_.getValue)
  }
}

给出以下编译错误:

[error] TestOp.scala:14: type mismatch;
[error]  found   : Any
[error]  required: Int
[error]     val x:Int = c ? (_.getValue)
[error]                   ^
[error] one error found
[error] {file:/home/mmalak/streaming-demo/}default-ae36bd/compile:compile: Compilation failed

一种解决方法是将 val x:Int 替换为 val x:java.lang.Integer,这样可以编译。有没有办法改进上面的 SafeDereference 以便允许 val x:Int ?

附加信息

以下产生所需的输出。现在的问题变成了如何将类型转换移动到 SafeDereference 中,以及如何处理所有其他 Scala“原语”(布尔等)。

object TestOp {

  class SafeDereference[A](obj: A) {
    def ?[B >: Null](function: A => B): B = if (obj == null) null else function(obj)
  }
  implicit def safeDereference[A](obj: A) = new SafeDereference(obj)

  class C { 
    def getValue: Int = 0                     
  }

  def main(args: Array[String]) {
    val c:C = null
    val x = (c ? (_.getValue)).asInstanceOf[java.lang.Integer].asInstanceOf[Int]
    println("x="+x)
  }
}

根据需要输出:

x=0
4

1 回答 1

2

你可以做这样的事情。该Zero特征允许您确定任何不是 的对象的零值nullable。在这种情况下,我为Numeric类型添加了一个:

object TestOp {

  trait Zero[T] {
    def apply(): T
  }

  object Zero {
    implicit def zeroNull[B >: Null] =
      new Zero[B] { def apply = null }

    implicit def zeroNumeric[B: Numeric] =
      new Zero[B] { def apply = implicitly[Numeric[B]].zero }
  }

  implicit class SafeDereference[A](obj: A) {
    def ?[B](function: A => B)(implicit zero: Zero[B]): B =
      if (obj == null) zero() else function(obj)
  }

  class C {
    def getValue: Int = 0
    def getSomething: C = new C
  }

  def main(args: Array[String]) {
    val c = new C
    val x = c ? (_.getValue)
    val y = c ? (_.getSomething)
  }
}

编辑

因为Boolean你会添加这样的东西:

implicit def zeroBoolean[B >: Boolean] =
  new Zero[B] { def apply = false }
于 2013-04-11T22:19:36.553 回答