Chad Minick
Software Developer

Option Pattern and avoiding Nulls pt. 1: Introduction

January 6, 2013 Comments, ,

I imagine in the PHP community, the idea of avoiding nulls in your code might be something new to think about. Because PHP is a dynamically typed language, nulls are handled much better compared to other languages. However, they do still cause a lot of issues. Two of the main places I see issues with nulls in PHP is method chaining and request variables. I'll make two more parts to this series to cover each. This is part 1: introduction to the Option pattern.

Nulls have been a headache for development ever since they started. I always tend to see new code in Java that hasn't been tested well and is full of NullPointerExceptions. Null's invention is attributed to C. A. R. Hoare, which he calls his "billion dollar mistake". Many new languages have looked into encouraging methods to avoid using null types.

With the rise of popularity of functional programming languages, Haskell has an interesting approach called a "Maybe Monad", which is a great way to represent something that could or could not be there. When Scala, a functional/object oriented hybrid language came across the same problem, they created an object oriented/functional approach of the Maybe Monad and called it an 'Option'. Option is an abstract type with two concrete implementations: Some and None. 'Some' naturally represents an option that has a value, while 'None' obviously represents an option without a value. Think of 'None' as a Null on steroids.

Google apparently likes this idea and added it to their Guava library for Java. I loved the pattern and now I've made one for PHP: https://github.com/cythrawll/Option.

Option Pattern in PHP is less needed than in languages like Scala and Java who try to have a high degree of type safety. Null is a really difficult bugger when it comes to type safety, however, like I said, PHP has a few places where Option Pattern could come in handy.

Here is some basic usage:

Let's say you have a function that sometimes may return null, there is a static method create($arg) on Option that will create either a 'Some' or 'None' instance.

$maybe = mightReturnNullOrSomething();
$option = Option::create($maybe);

Options can also let you handle undefined variables.

$option = Option::create($nonexistingvariable);

Note that create($arg) considers only unset variables or null as empty. Things like an empty array, or an empty string, 0, etc. are all considered to have a value.

$maybe = "";
$option = Option::create($maybe);
$option->isEmpty(); //returns false!
$option->isDefined(); //returns true!

You could use the get() method to get the actual value out.

echo $option->get();

This will work if $option has a value, however if it's empty, it will throw an Exception! So you should avoid using get() yourself unless you test it first with isEmpty() or isDefined().

Probably the most used method here is getOrElse. This allows you to pass a default in case there is no value:

echo $option->getOrElse("default");

Sometimes you might need to pass something you're carrying around as an Option as a null, because that's what a function you are using expects! PHP sometimes wants a null when you mean nothing. getOrNull() helps with that.

functionThatMightNeedNull($option->getOrNull());

Last but not least, we have map(). map() takes in a callable type such as a callback or an anonymous function, and returns the result of applying that to the option's value, or None if there is no value.

$string = "hello";
$option = Option::create($string);
echo $option->map('strtoupper'); //outputs 'HELLO';
echo $option->map(function($s) { return strtoupper($s); }); //does same thing

We will show the cool things you can do with map(); in part two!

Note: Option project on github uses namespaces, so make sure you use the namespace before trying these examples!:

use org\codeangel\option\Option;

Links

Option github poject: https://github.com/cythrawll/Option
Part 2
Part 3

comments powered by Disqus
Chad Minick | Software Developer
Twitter | Github | LinkedIn