Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@CHH
Last active May 15, 2017 06:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CHH/9c6e14a130e6a38482b02cfc05a56dd6 to your computer and use it in GitHub Desktop.
Save CHH/9c6e14a130e6a38482b02cfc05a56dd6 to your computer and use it in GitHub Desktop.
<?php
function id(callable $fn) {
if (is_string($fn)) {
return "function_$fn";
} elseif (is_array($fn)) {
return "method_{$fn[0]}::{$fn[1]}";
} elseif ($fn instanceof \Closure) {
return "closure_".spl_object_hash($fn);
}
}
function arity(callable $fn): int {
static $reflected = [];
$id = id($fn);
if (array_key_exists($id, $reflected)) {
return $reflected[$id]->getNumberOfParameters();
}
if (is_string($fn) || $fn instanceof Closure) {
$reflected[$id] = new ReflectionFunction($fn);
} elseif (is_array($fn)) {
$reflected[$id] = new ReflectionMethod(...$fn);
} else {
return -1;
}
return $reflected[$id]->getNumberOfParameters();
}
function callRight(callable $fn, ...$curry) {
if (count($curry) === arity($fn)) {
return $fn(...$curry);
} else {
return function (...$args) use ($fn, $curry) {
$args = array_merge($args, $curry);
if (count($args) === arity($fn)) {
return $fn(...$args);
}
return call($fn, ...$args);
};
}
}
function call(callable $fn, ...$curry) {
if (count($curry) === arity($fn)) {
return $fn(...$curry);
} else {
return function (...$args) use ($fn, $curry) {
$args = array_merge($curry, $args);
if (count($args) === arity($fn)) {
return $fn(...$args);
}
return call($fn, ...$args);
};
}
}
function apply(callable $fn, array $curry) {
return call($fn, ...$curry);
}
function applyRight(callable $fn, array $curry) {
return callRight($fn, ...$curry);
}
function unary(callable $fn): callable {
return function ($_) use ($fn) {
return $fn($_);
};
}
function binary(callable $fn): callable {
return function ($_1, $_2) use ($fn) {
return $fn($_1, $_2);
};
}
function _column(array $ary, string $columnKey) {
return array_column($ary, $columnKey);
}
function pluck(...$args): callable {
return apply(binary('array_column'), $args);
}
function pluckWith(...$args): callable {
return applyRight(binary('array_column'), $args);
}
function _array_filter_with_key_passed(array $ary, callable $fn) {
return array_filter($ary, $fn, ARRAY_FILTER_USE_BOTH);
}
function filter(array $ary) {
return call('_array_filter_with_key_passed', $ary);
}
function filterWith(callable $fn) {
return callRight('_array_filter_with_key_passed', $fn);
}
function map(array $ary) {
return callRight('array_map', $ary);
}
function mapWith(callable $fn) {
return call('array_map', $fn);
}
function getWith($property): callable {
return unary(function ($object) use ($property) {
return $object->{$property} ?? null;
});
}
function getWithKey($key): callable {
return unary(function (array $item) use ($key) {
return $item[$key] ?? null;
});
}
function isNot(callable $predicate): callable {
return function ($value) use ($predicate): bool {
return !$predicate($value);
};
}
function ofType($type) {
return function ($value) use ($type): bool {
$fn = "is_{$type}";
return $fn($value);
};
}
function equalTo($predicate): callable {
return function ($value) use ($predicate): bool {
return $value === $predicate;
};
}
function is(callable $predicate): callable {
return $predicate;
}
function _send($object, string $method, ...$args) {
return $object->{$method}(...$args);
}
function send($method, ...$args) {
return callRight('_send', $method, ...$args);
}
function sendWith($object) {
return call('_send', $object);
}
function maybe($fn): callable {
return function ($value) use ($fn) {
return $value === null
? $value
: $fn($value);
};
}
function valueOf($value): callable {
return is_callable($value)
? $value
: function () use ($value) { return $value; };
}
function sequence(...$predicates): callable {
return function () use ($predicates) {
$returnValue = null;
while ($predicate = array_shift($predicates)) {
$returnValue = $predicate($returnValue);
}
return $returnValue;
};
}
function sequenceNow(...$predicates) {
return sequence(...$predicates)();
}
function compose(...$predicates) {
return function () use ($predicates) {
$returnValue = null;
while ($predicate = array_pop($predicates)) {
$returnValue = $predicate($returnValue);
}
return $returnValue;
};
}
function composeNow(...$predicates) {
return compose(...$predicates)();
}
function hello($first, $last) {
return "Hi $first $last!";
}
var_dump(call("hello", "Christoph", "Hochstrasser"));
$hello = call("hello", "Christoph");
var_dump($hello("Hochstrasser"));
var_dump(call("hello")("Christoph")("Hochstrasser"));
$l = ["foo", "bar", "baz"];
$mapUpper = call('array_map', unary('strtoupper'));
var_dump(mapWith(unary('strtoupper'))($l));
var_dump($mapUpper($l));
$users = [
[
'first' => 'Max',
'last' => 'Mustermann',
],
2,
[
'first' => 'Susi',
'last' => 'Mustermann',
],
[
'first' => 'Joe',
'last' => 'Johnson',
],
null,
1,
[
'first' => 'Carl',
'last' => 'Carlson',
],
];
var_dump(
sequenceNow(
valueOf($users),
filterWith(is(ofType('array'))),
pluckWith('first')
)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment