Skip to main content

Pattern Matching

The goal of pattern matching is to return a value from an expression that corresponds to a unique sequence. Pattern matching is, for those unfamiliar with many of its intimacies, similar to the switch statement. The patterns used in the pattern-matching function are a near facsimile of the Haskell pattern-matching patterns. Because pattern matching is a core feature of a language like Haskell, implementing it in PHP is quite the uphill task. The bingo-functional library has two pattern matching functions that conform to the patterns shown in the table below: match and patternMatch.

Pattern nameFormatExamples
constantA scalar value12, 12.02, "foo"
variableAny value identifierfoo, bar, baz
array[constant, ..., variable]'["foo", "bar", baz]'
cons(identifier:identifier)(foo:bar:_)
objectsAn objectstdClass::class
wildcard_'_'

Versions of the library v1.13.0 and newer include Gilles Crettenand's pattern-matching library.

cmatch#

cmatch(patterns)

cmatch :: [(a -> b)] -> [a] -> b

Since: v1.8.0

Arguments:

  • patterns (array) - The patterns to evaluate
  • values (array) - The values for comparison

The match function deals primarily with cons, values separated by a colon. The cons serve as arguments for the accompanying lambdas: each cons pattern has a wildcard before its closing brace.

use function Chemem\Bingo\Functional\PatternMatching\cmatch;
$match = cmatch([  '(x:xs:_)'  => fn (int $x, int $xs): int => $x ** $xs,  '(x:_)'     => fn (int $x): int => $x ** 2,  '_'         => fn (): int => 0]);
$result = $match([10, 5]);

patternMatch#

patternMatch(patterns, values)

patternMatch :: [(a -> b)] -> a -> b

Since: v1.8.1

Arguments:

  • patterns (array) - The patterns to evaluate
  • values (mixed) - The values for comparison

The pattern match function is useful for array content comparisons like URL and switch statement-driven matches. The patternMatch function combines arrays, constants, and variables and assesses the specificity of each pattern provided.

The patternMatch function can detect string matches for single scalar values and evaluate the right function bindings based on value specifics.

use Chemem\Bingo\Functional as f;use function Chemem\Bingo\Functional\PatternMatching\patternMatch;
const DATA = [  'socials' => [    'twitter' => '@agiroLoki',    'github' => '@ace411'  ],  'repos'   => [    'bingo-functional',    'bingo-functional-js',    'bingo-functional-repl'  ]];
$pluck = f\partial(f\pluck, DATA);
$match = patternMatch([  '[_, "repos"]'            => fn () => $pluck('repos'),  '["chemem", "socials"]'   => fn () => $pluck('socials'),  '_'                       => fn () => []], explode('/', 'loki/repos'));

Important

  • Added in version 1.10.0 is the object match feature - convenient for comparing class instances.
  • Added in version 1.11.0 is the wildcard match feature. See issue #12.

letIn#

letIn(patterns, list)

letIn :: String -> [a] -> ([String] -> (a -> b) -> b) -> b

Since: v1.11.0

Arguments:

  • patterns (string) - The patterns that serve as the basis for deconstruction
  • list (array) - The list to deconstruct
  • args (array) - The arguments to use in the deconstruction operation
  • operation (callable) - The deconstruction operation

In Elm, it is possible to deconstruct lists (tuples and records) via pattern matching with let-in syntax. An example like the one below is a demonstration of such an operation:

numbers =    ( 1, 9, 7, 13 )
let (a, b, c, d) =    numbers        in            a + b + c + d-- output is 30

The result of execution of the code in the snippet above is the integer value 30. The let segment creates aliases for the values in the numbers tuple - something akin to the usage of the list directive in PHP. Also, said syntax scopes all the aliases (a, b, c, and d) to the operations in the in-section of the code. The bingo-functional implementation of the same snippet - a higher-order function - is as follows:

use function Chemem\Bingo\Functional\PatternMatching\letIn;
$numbers  = [1, 9, 7, 13];
$let      = letIn('[_, _, c, d]', $numbers);
$in       = $let(['c', 'd'], fn (int $c, int $d): int => $c * $d);