+3  A: 

Monadic bind (flatMap/map) with the scala.Option type. Support is also provided by for-comprehensions. Scalaz provides an applicative functor style if you prefer.

This is not equivalent, but a far better solution than Groovy's operator for many reasons.

can you give an example?
Antony Stubbs
An example:Some(5).map(_+5) == Some(10)val foo:Option[Int] = Nonefoo.map(_+5) == None
Kim
+4  A: 

There are two things that need to be considered here.

First, there is the problem of the "nothing". How do you chain things when a part of the chain may not return anything? The answer is using Option and for comprehensions. For example:

scala> case class Address(city: Option[String] = None, street: Option[String] = None, number: Option[Int] = None)
defined class Address

scala> case class Contact(name: String, phone: Option[String] = None, address: Option[Address] = None)
defined class Contact

scala> case class ContactDetails(phone: Option[String] = None, address: Option[Address] = None)
defined class ContactDetails

scala> case class Contact(phone: Option[String] = None, address: Option[Address] = None)
defined class Contact

scala> case class Person(name: String, contactDetails: Option[Contact] = None)
defined class Person

scala> case class Company(name: String, contactPerson: Option[Person] = None)
defined class Company

scala> val p1 = Company("ABC", Some(Person("Dean", Some(Contact(None, Some(Address(city = Some("New England"))))))))
p1: Company = Company(ABC,Some(Person(Dean,Some(Contact(None,Some(Address(Some(New England),None,None)))))))

scala> val p2 = Company("Finnicky", Some(Person("Gimli", None)))
p2: Company = Company(Finnicky,Some(Person(Gimli,None)))

scala> for(company <- List(p1, p2);
     | contactPerson <- company.contactPerson;
     | contactDetails <- contactPerson.contactDetails;
     | address <- contactDetails.address;
     | city <- address.city) yield city
res28: List[String] = List(New England)

This is how you are supposed to write code which may return something or not in Scala.

The second problem, of course, is that sometimes you may not have access to the source code to do the proper convertion. In this case, there is some additional syntax overhead to be head, unless an implicit can be used. I'll give an example below, in which I use an "toOption" function -- there is such a thing on Scala 2.8, of which I'll talk about below.

scala> def toOption[T](t: T): Option[T] = if (t == null) None else Some(t)
toOption: [T](t: T)Option[T]

scala> case class Address(city: String = null, street: String = null, number: Int = 0)
defined class Address

scala> case class Contact(phone: String = null, address: Address = null)
defined class Contact

scala> case class Person(name: String, contactDetails: Contact = null)
defined class Person

scala> case class Company(name: String, contactPerson: Person = null)
defined class Company

scala> val p1 = Company("ABC", Person("Dean", Contact(null, Address(city = "New England"))))
p1: Company = Company(ABC,Person(Dean,Contact(null,Address(New England,null,0))))

scala> val p2 = Company("Finnicky", Person("Gimli"))
p2: Company = Company(Finnicky,Person(Gimli,null))

scala> for(company <- List(p1, p2);
     | contactPerson <- toOption(company.contactPerson);
     | contactDetails <- toOption(contactPerson.contactDetails);
     | address <- toOption(contactDetails.address);
     | city <- toOption(address.city)) yield city
res30: List[String] = List(New England)

Remember that you can be quite creative in naming a function. So, instead of "toOption", I might have named it "?", in which case I'd write things like "?(address.city)".

Thanks to nuttycom for reminding me, on Scala 2.8 there is an Option factory on the object Option, so I can just write Option(something). In effect, you can replace "toOption" above with "Option". And if you prefer using ?, you can just use import with rename.

Daniel
The method you're thinking of in 2.8 is Option.apply(). Thus, just as you have Some(a) and None, you now have Option(a) which returns if (a == null) None else Some(a)
Kris Nuttycombe
Given 2.8, you could actually get your "?" by simply doing import scala.{Option => ?}
Kris Nuttycombe
+5  A: 

How about this?

def ?[A](block: => A) =
  try { block } catch {
    case e: NullPointerException if e.getStackTrace()(2).getMethodName == "$qmark" => null
    case e => throw e
  }

Using this little snippet, you can dereference safely and the code itself is quite succinct:

val a = ?(b.c.d.e)

a == null if b or b.c or b.c.d or b.c.d.e is null, otherwise, a == b.c.d.e

I think the value of a safe-dereference operator is diminished when you are using a language like Scala which has facilities like call-by-name and implicits.

ps: I modify the code above a bit in light of one of the comments below to handle the case when NullPointerException is actually thrown inside the called function.

BTW, I think using the function below is a more idiomatic way of writing Scala:

def ??[A](block: => A): Option[A] = ?(block) match {
    case a: A => Some(a)
    case _ => None
  }

like so:

??(a.b.c.d) match {
    case Some(result) => // do more things with result
    case None => // handle "null" case
  }
Walter Chang
Of course! Beautiful! Yet again I am seriously impressed with Scala! This is even better than the Groovy operator! I wonder if you can do the same with closures in Groovy? Definitely gonna add this one to the tool box! To appear in Wicket-Scala extensions soon... Thanks!
Antony Stubbs
A demo:scala> def ?[A](block: => A) = | try { block } catch { case e: NullPointerException => null }$qmark: [A](=> A)Anyscala> case class Address(city:String)scala> case class Person(a:Address)scala> case class Company(p:Person)scala> var a = Company(Person(Address("Customs st")))a: Company = Company(Person(Address(Customs st)))scala> var b = Company(Person(null))b: Company = Company(Person(null))scala> println(a.p.a.city)Customs stscala> println(b.p.a.city)java.lang.NullPointerExceptionscala> println(?(b.p.a.city))null
Antony Stubbs
perhaps you could edit your comment and add that demo in, but with line breaks?
Antony Stubbs
This is kinda crap if one of the method calls actually throws an NPE.
Jevgeni Kabanov
What if you catch a nested exception from inside another method called $qmark? :P
Jevgeni Kabanov
For comprehension is a safer option, really.
Jevgeni Kabanov
the 3rd stack frame is THE stack frame for this function. as long as the function is called "?", we are pretty safe.
Walter Chang
The stack frame thing is ingenius. Using reflection can make the code much slower, though. This _is_ rather safe, but using it on a critical path can be unexpectedly unpleasant.
Daniel
Anyway, you have my vote. It's clever.
Daniel
However - it only uses reflection when an actual exception is thrown - so in that case we don't usually care about performance :)
Antony Stubbs
+1  A: 

Because this would look terrible as a comment, here's a commented version of Walter's code:

/**
 * Safe dereference operator. E.g. ?(a.b.c.null.dd)
 */
def ?[A](block: => A) = {
  try { block } catch {
    // checks to see if the 3rd to last method called in the stack, is the ?() function, 
    // which means the null pointer exception was actually due to a null object, 
    // otherwise the ?() function would be further down the stack.
    case e: NullPointerException if e.getStackTrace()(2).getMethodName == "$qmark" => {null}
    // for any other NullPointerException, or otherwise, re-throw the exception.
    case e => throw e
  }

And the specification, which passes:

case class Company(employee:Employee)
case class Employee(address:Address){
  def lookupAddressFromDb:Address = throw new NullPointerException("db error")
}
case class Address(city:String)

"NullSafe operater" should {
  "return the leaf value when working with non-null tree" in {
    val company = Company(Employee(Address("Auckland")))
    val result = ?( company.employee.address.city )
    result mustEq "Auckland"
  }
  "return null when working with a null element at some point in the tree" in {
    val company = Company(null)
    val result = ?( company.employee.address.city )
    result must beNull
  }
  "re-throw the NPE when working with a method which actually throws a NullPointerException" in {
    val company = Company(Employee(Address("Auckland")))
    ?( company.employee.lookupAddressFromDb.city ) aka "the null-safe lookup method" must throwA[NullPointerException]
  }   
}
Antony Stubbs
+1  A: 

Not mine but a coworker's

class NullCoalescer[T <: AnyRef](target: T) {
    def ?? (other: T) =
        if(target == null) other else target
}
object NullCoalescerConversions {
    implicit def toNullCoalescer[T <: AnyRef](target: T): NullCoalescer[T] = 
        new NullCoalescer(target)
}

println (System.getProperty("maybe") ?? "definitely")
Jed Wesley-Smith