24

NPE を捕まえて、スタック トレースから破壊された名前を浚渫しようとするようなホラー ショーを含む、このような質問から回答が得られるのを見たので、回答できるようにこの質問をしています。

コメントまたはさらなる改善を歓迎します。

4

2 に答える 2

38

そのようです:

case class ?:[T](x: T) {
  def apply(): T = x
  def apply[U >: Null](f: T => U): ?:[U] =
    if (x == null) ?:[U](null)
    else ?:[U](f(x))
}

そして実際に:

scala> val x = ?:("hel")(_ + "lo ")(_ * 2)(_ + "world")()
x: java.lang.String = hello hello world

scala> val x = ?:("hel")(_ + "lo ")(_ => (null: String))(_ + "world")()
x: java.lang.String = null
于 2009-09-01T20:01:56.463 に答える
0

追加したorElse

case class ?:[T](x: T) {
  def apply(): T = x
  def apply[U >: Null](f: T => U): ?:[U] =
    if (x == null) ?:[U](null)
    else ?:[U](f(x))
  def orElse(y: T): T = 
    if (x == null) y
    else x
}
scala> val x = ?:(obj)(_.subField)(_.subSubField).orElse("not found")
x: java.lang.String = not found

または、演算子構文ではなく名前付き構文を好む場合

case class CoalesceNull[T](x: T) {
  def apply(): T = x
  def apply[U >: Null](f: T => U): CoalesceNull[U] =
    if (x == null) CoalesceNull[U](null)
    else CoalesceNull[U](f(x))
  def orElse(y: T): T =
    if (x == null) y
    else x
}
scala> val x = CoalesceNull(obj)(_.subField)(_.subSubField).orElse("not found")
x: java.lang.String = not found

その他の例

case class Obj[T](field: T)

  test("last null") {
    val obj: Obj[Obj[Obj[Obj[String]]]] = Obj(Obj(Obj(Obj(null))))
    val res0 = CoalesceNull(obj)(_.field)(_.field)(_.field)(_.field)()
    res0 should === (null)
    val res1 = CoalesceNull(obj)(_.field)(_.field)(_.field)(_.field).orElse("not found")
    res1 should === ("not found")
  }

  test("first null") {
    val obj: Obj[Obj[Obj[Obj[String]]]] = null
    val res0 = CoalesceNull(obj)(_.field)(_.field)(_.field)(_.field)()
    res0 should === (null)
    val res1 = CoalesceNull(obj)(_.field)(_.field)(_.field)(_.field).orElse("not found")
    res1 should === ("not found")
  }

  test("middle null") {
    val obj: Obj[Obj[Obj[Obj[String]]]] = Obj(Obj(null))
    val res0 = CoalesceNull(obj)(_.field)(_.field)(_.field)(_.field)()
    res0 should === (null)
    val res1 = CoalesceNull(obj)(_.field)(_.field)(_.field)(_.field).orElse("not found")
    res1 should === ("not found")
  }

  test("not null") {
    val obj: Obj[Obj[Obj[Obj[String]]]] = Obj(Obj(Obj(Obj("something"))))
    val res0 = CoalesceNull(obj)(_.field)(_.field)(_.field)(_.field)()
    res0 should === ("something")
    val res1 = CoalesceNull(obj)(_.field)(_.field)(_.field)(_.field).orElse("not found")
    res1 should === ("something")
  }
}
于 2021-04-21T00:02:43.360 に答える