Skip to content

Instantly share code, notes, and snippets.

@alganet
Last active January 22, 2026 12:29
Show Gist options
  • Select an option

  • Save alganet/61729dc56c6c976b6bb22a6550efe5eb to your computer and use it in GitHub Desktop.

Select an option

Save alganet/61729dc56c6c976b6bb22a6550efe5eb to your computer and use it in GitHub Desktop.
Exploring PHP 8.5 pipe goodies
<?php
declare(strict_types=1);
// ISC License
// Copyright (c) 2025, Alexandre Gomes Gaigalas <alganet@gmail.com>
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
function begin() {
return (static fn () => yield from [])();
}
function check(Closure $fn, $message) : Closure {
return static fn (Generator $it): Generator => yield from [
...$it,
static fn ($v) => $fn($v) ? null : $message
];
}
function collect(Closure $step) : Closure {
return static function (Generator $it) use ($step): Closure
{
$acc = static fn ($v) => [];
foreach ($it as $fn) {
$acc = static fn ($v) => $step($acc, $fn, $v);
}
return $acc;
};
}
function allMustPass() : Closure {
return collect(
static fn ($acc, $fn, $v) => array_merge(
$acc($v),
(($m = $fn($v)) === null) ? [] : [$m]
)
);
}
function oneMustPass() : Closure {
return collect(
static fn ($acc, $fn, $v) => (($m = $fn($v)) === null)
? []
: array_merge($acc($v), [$m])
);
}
function validate(mixed $value): Closure {
return static fn (Closure $fn) => $fn($value);
}
$base = fn () => begin()
|> check(is_int(...), 'must be an integer')
|> check(is_scalar(...), 'must be a scalar');
echo "Must be both int and scalar: 42 should return 0 messages\n";
var_dump($base() |> allMustPass() |> validate(42));
echo "Must be both int and scalar: 'hello' should return 1 message\n";
var_dump($base() |> allMustPass() |> validate('hello'));
echo "Must be either int or scalar: 42 should return 0 messages\n";
var_dump($base() |> oneMustPass() |> validate(42));
echo "Must be either int or scalar: [] should return 2 messages\n";
var_dump($base() |> oneMustPass() |> validate([]));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment