Skip to content

Instantly share code, notes, and snippets.

@AnandPilania
Created March 15, 2023 01:59
Show Gist options
  • Save AnandPilania/24052781effe1e5b9e078ef3a2e7b3dc to your computer and use it in GitHub Desktop.
Save AnandPilania/24052781effe1e5b9e078ef3a2e7b3dc to your computer and use it in GitHub Desktop.
NUTTY Pipe
<?php
function pipe($subject) {
return new Pipe($subject);
}
class Pipe implements \Stringable, \ArrayAccess, \IteratorAggregate
{
use Transparency;
function __construct($target)
{
$this->target = $target;
}
function __invoke(...$params) {
if (empty($params)) return $this->target;
[ $before, $through, $after ] = [ [], null, [] ];
foreach ($params as $key => $param) {
if (! $through) {
if (is_callable($param)) $through = $param;
else $before[$key] = $param;
} else {
$after[$key] = $param;
}
}
$params = [ ...$before, $this->target, ...$after ];
$this->target = $through(...$params);
return $this;
}
}
trait Transparency
{
public $target;
function __toString()
{
return (string) $this->target;
}
function offsetExists(mixed $offset): bool
{
return isset($this->target[$offset]);
}
function offsetGet(mixed $offset): mixed
{
return $this->target[$offset];
}
function offsetSet(mixed $offset, mixed $value): void
{
$this->target[$offset] = $value;
}
function offsetUnset(mixed $offset): void
{
unset($this->target[$offset]);
}
function getIterator(): \Traversable
{
return (function () {
foreach ($this->target as $key => $value) {
yield $key => $value;
}
})();
}
}
<?php
function pipe($thing) {
$fluent = new class ($thing) {
public $calls = 0;
public $ticks = 0;
public $onTick;
public $kill = false;
public $fluent;
public function __construct(public $thing) {}
public function setFluentRef(&$fluent)
{
$this->fluent = $fluent;
}
public function &__invoke(...$params) {
if (empty($params)) return $this->thing;
$this->calls++;
$before = [];
$through = null;
$after = [];
foreach ($params as $key => $param) {
if (! $through) {
if (is_callable($param)) $through = $param;
else $before[$key] = $param;
} else {
$after[$key] = $param;
}
}
$params = array_merge($before, [$this->thing], $after);
$this->thing = $through(...$params);
$this->ticks = 0;
declare(ticks=1);
return $this->fluent;
}
};
$fluent->setFluentRef($fluent);
$onTick = function () use (&$fluent) {
if (is_string($fluent)) return;
if ($fluent->ticks === 1 && $fluent->calls === 0) {
$fluent->fluent = $fluent->thing;
}
$fluent->ticks++;
$fluent->calls = 0;
};
register_tick_function($onTick);
return $fluent;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment