yitznewton / maybe-php
A Maybe monad implementation for PHP
Requires
- php: >=5.4
Requires (Dev)
- fabpot/php-cs-fixer: dev-master
- phpmd/phpmd: ~2.0
- phpunit/phpunit: ~4.0
- squizlabs/php_codesniffer: ~1.0
This package is not auto-updated.
Last update: 2024-11-05 03:16:08 UTC
README
A Maybe monad implementation for PHP
This project was wholly inspired by a blog post by @linepogl.
Motivation
Dealing with null
values (and, in PHP, falsy values) is tedious and prone
to developer error (viz the null pointer exception, trying to dereference
a null
).
In my exposure to Haskell, I learned about the awesomeness of pattern matching,
whereby you can get the compiler to force yourself to handle all possibilities.
This combines with a tool called Maybe
to require specific handling for
"null" and "non-null" possibilities.
PHP does not offer pattern matching, but we can still use classes to wrap raw values, and require us to handle null conditions, without repeated explicit null checking and conditionals.
Examples
Simple
Before:
$blogpost = $repository->get($blogpostId); echo $blogpost->teaser(); // oh noe! what if $blogpost is null?! :boom:
After:
$blogpost = new \Yitznewton\Maybe\Maybe($repository->get($blogpostId)); echo $blogpost->select(function ($bp) { $bp->teaser(); })->valueOr('No blogpost found');
With callback
$blogpost = new \Yitznewton\Maybe\Maybe($repository->get($blogpostId)); $callback = function () { return someExpensiveOperation(); }; echo $blogpost->select(function ($bp) { $bp->teaser(); })->valueOrCallback($callback);
Loose-falsy
// $process->execute() normally returns a result object, but sometimes returns false $result = new LooseMaybe($process->execute()); echo $result->select(function ($resultObject) { $resultObject->getStatus(); })->valueOr('failed'); // echoes 'failed' when the result was false
Performance
In a simple test using PHP 5.5, performance was approximately 20% that of
a straight is_null()
check in an if/else conditional. In other words it
takes 5 times as long to run.
You can reproduce the test locally by running the profiling testsuite in
PHPUnit. You will first need to install XHProf, and override the XHProf lib
directory using a local phpunit.xml
config.
$ ./vendor/bin/phpunit --testsuite=profiling
Dictionary wrapper
maybe-php includes an array wrapper called Dictionary
, whereby trying to
access properties on the wrapper will return a Maybe
object. You can specify
whether to return a plain Maybe
(default) or a LooseMaybe
.
$dictionary = new \Yitznewton\Maybe\Dictionary([ 'foo' => 'bar', ]); $dictionary->foo->valueOr('quux'); // 'bar' $dictionary->noSuchKey->valueOr('quux'); // 'quux' // with LooseMaybe $dictionary = new \Yitznewton\Maybe\Dictionary([ 'foo' => false, ], \Yitznewton\Maybe\LooseMaybe::class); $dictionary->foo->valueOr('quux'); // 'quux', because loose falsy