Best Scala imitation of Groovy's safe-dereference operator (?.)?

前端 未结 8 2055
心在旅途
心在旅途 2020-12-02 12:43

I would like to know what the best Scala imitation of Groovy\'s safe-dereference operator (?.), or at least some close alternatives are?

I\'ve discussed it breifly o

8条回答
  •  伪装坚强ぢ
    2020-12-02 13:04

    To follow up Daniel C. Sobral's answer, the reason Option is preferred is because idiomatic Scala does not use null pointers. If you can, rewrite the code to return Options instead of nullable references. Chained flatMaps are cleaner than for-comprehensions, since you don't need a new variable name for each step. If all the values are optional (as in the Groovy example), the Scala approach would look like this:

    (company flatMap _.getContactPerson
             flatMap _.getContactDetails
             flatMap _.getAddress
             flatMap _.getCity) match {
      case Some(city) => ...
      case None       => ...
    }
    

    If you must use nullable values for Java interoperability, here's an approach that gives you safety without NPE-wrangling or too much clutter:

    sealed trait Nullable[+A] {
      def apply[B](f:A=>B): Nullable[B]
    }
    
    def ?[A](a: A) = a match {
      case null => NullRef
      case _    => Ref(a)
    }
    
    case class Ref[A](value: A) extends Nullable[A] {
      def apply[B](f:A=>B) = ?(f(value))
    }
    
    object NullRef extends Nullable[Nothing] {
      def apply[B](f: Nothing=>B): Nullable[B] = NullRef
    }
    
    
    ?(company)(_.getContactPerson)(_.getContactDetails)(_.getAddress)(_.getCity) match {
      case Ref(city) => ...
      case _         => ...
    }
    

    This should be easy to expand to a full Option-style monad if desired.

提交回复
热议问题