Null-safe dereferencing in Drools patterns
Tony Hoare introduced Null references in ALGOL W back in 1965 “simply because it was so easy to implement”. After many years he regretted his decision calling it "my billion dollar mistake".http://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare
Unfortunately the vast majority of the languages created in the last decades have been built with the same wrong design decision so language designers and software engineers started to look for workarounds to avoid the infamous NullPointerException.
Functional languages like Haskell or Scala structurally resolve this problem by wrapping the nullable values in an Option/Maybe monad. Other imperative languages like Groovy introduced a null-safe dereferencing operator (?. operator) to safely navigate values that could be potentially null.http://groovy.codehaus.org/Operators#Operators-ElvisOperator
A similar features has been proposed (and then discarded) as part of the project Coin in Java 7http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000047.html
Despite I personally prefer the functional approach, I also understand that it would be impratical in a declarative language like the LHS of the Drools rules, so I decided to further explore the possibility to introduce a null-safe dereferencing operator. For instance what Groovy does with this regards is that having the statement:
def streetName = person?.address?.street
then streetName will be null if person or person.address is null and of course no NPE will be thrown. Translating this in the Drools pattern matching language we could have something like:
Person( $streetName : address?.street )
where of course $streetName will be bound to a null both if the user has no address and if the address has no street. It also implies that, in case of a null address, the following pattern will match positively:
Person( address?.street == null )
This last behaviour could look not completely intuitive or satisfying under a pattern matching persepctive and things become even more blurred when dealing with primitive types. For example we have that the pattern:
Person ( $income : job?.salary == 0 )
should match both when the person has no job at all and when he works for free. To return 0 from the expression job?.salary when job is null is just a (questionable) convention but at the moment it seems to be the only meaningful thing to do to avoid an NPE (embarassing when using an operator that is supposed to be null-safe) caused by the Java autounboxing mechanism.
This behaviour can seem reasonable in an imperative language but looks not completely correct under a pattern matching point of view. Moreover, in this last context, we can also give a different interpretation of how the null-safe dereferencing should work. I will use another symbol, !. (but it can change in the future) to underline its different behavior. In this alternative meaning the matching algorithm requires the value to the left of the !. operator to be not null in order to give a positive result for pattern matching itself. In other words the pattern:
Person( $streetName : address!.street )
will be internally translated in:
Person( address != null, $streetName : address.street )
Note that doing so we are saying that what looks like a simple binding without any constraint can actually cause the pattern matching to return a negative result. In reality, as we saw, that pattern has the constraint address != null even if it is hidden behind the !. operator.
Also note that the behaviour introduced with this second operator resolves any ambiguity related with primitive types. Indeed the pattern:
Person ( $income : job!.salary == 0 )
will be traslated in:
Person ( job != null, $income : job.salary == 0 )
This last pattern will match if and only if the person has a job but he does it for free. This behaviour looks far more coherent with the pattern matching perspective.
Both the ?. and !. operators, with their different meanings, could be useful for the Drools users, but for the reasons stated above, we believe that the second fits better and more naturally the pattern matching point of view, so we will start adding it to the Drools language, not excluding we will decide to implement also the other one in a second stage.