functional-php / pattern-matching
Pattern matching for PHP with automatic destructuring.
Installs: 36 955
Dependents: 0
Suggesters: 0
Security: 0
Stars: 82
Watchers: 4
Forks: 4
Open Issues: 7
Requires
- php: >=5.6.0
Requires (Dev)
- atoum/atoum: ^3 || ^4
- atoum/reports-extension: ^3 || ^4
- friendsofphp/php-cs-fixer: ~2 || ~3
README
Pattern matching is the process of checking a series of token against a pattern.
It is different from pattern recognition as the match needs to be exact.
The process does not only match as a switch statement does, it also assigns the value
a bit like the list
construct in PHP, a process called destructuring.
Most functional languages implement it as a core feature. Here is are some small examples in Haskell:
fact :: (Integral a) => a -> a fact 0 = 1 fact n = n * fact (n-1) head :: [a] -> a head xs = case xs of [] -> error "empty list" (x:_) -> x firstThree :: [a] -> (a, a, a) firstThree (x:y:z:_) = (x, y, z) firstThree _ = error "need at least 3 elements"
If you want to read more about the topic, you can head over to Wikipedia : Pattern matching
Installation
composer require functional-php/pattern-matching
Basic Usage
As we cannot extend the syntax of PHP, the choice was made to use a syntax based on arrays. The key representes the pattern and the value is the function to call with the value or a constant if you want to do nothing with it.
Let's see how we could implement our 3 Haskell examples:
use FunctionalPHP\PatternMatching as m; $fact = m\func([ '0' => 1, 'n' => function($n) use(&$fact) { return $n * $fact($n - 1); } ]); $head = m\func([ '(x:_)' => function($x) { return $x; }, '_' => function() { throw new RuntimeException('empty list'); } ]); $firstThree= m\func([ '(x:y:z:_)' => function($x, $y, $z) { return [$x, $y, $z]; }, '_' => function() { throw new RuntimeException('need at least 3 elements'); } ]);
You can also use the match
function if you want to have a beefed up version of the switch
statement or if you don't like anonymous functions:
use FunctionalPHP\PatternMatching as m; function factorial($n) { return m\pmatch([ '0' => 1, 'n' => function($n) use(&$fact) { return $n * factorial($n - 1); } ], $n); } echo m\pmatch([ '"toto"' => 'first', '[a, [b, c], d]' => 'second', '[a, _, (x:xs), c]' => 'third', '_' => 'default', ], [1, 2, ['a', 'b'], true]); // third
If you are just interested in destructuring your values, there is also a helper for that:
use FunctionalPHP\PatternMatching as m; print_r(m\extract([1, 2, ['a', 'b'], true], '[a, _, (x:xs), c]')); // Array ( // [a] => 1 // [x] => a // [xs] => Array ( [0] => b ) // [c] => 1 // )
Patterns
Here is a quick recap of the available patterns:
Testing
You can run the test suite for the library using:
composer test
A test report will be available in the reports
directory.
Contributing
Any contribution welcome :
- Ideas
- Pull requests
- Issues