Last active
April 19, 2017 18:15
-
-
Save jeremeamia/bafd3557a35c8949f64d57f520169a68 to your computer and use it in GitHub Desktop.
Revisions
-
jeremeamia revised this gist
Apr 19, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -57,7 +57,7 @@ function from_method($class, $method = null) { } list($class, $object) = determine_subject($class); if (!method_exists($class, $method)) { throw new IAE('Expected the method to exist.'); } -
jeremeamia revised this gist
Apr 19, 2017 . 1 changed file with 115 additions and 104 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,119 +1,130 @@ <?php namespace fn { use Closure as Fn; use InvalidArgumentException as IAE; const SKIP = "\0...\0"; /** * @param callable $fn * @param mixed $scope * @return Fn */ function scope(callable $fn, $scope) { list($scope, $object) = determine_subject($scope); return from_callable($fn)->bindTo($object, $scope); } /** * @param string $function * @return Fn */ function from_function($function) { if (!is_string($function)) { throw new IAE('Expected the name of a function or static method to be provided.'); } if (strpos($function, '::') > 0) { return from_method(...explode('::', $function, 2)); } if (!is_callable($function)) { throw new IAE('Expected the function to exist and be callable.'); } return from_callable($function); } /** * @param mixed $class * @param string|null $method * @return Fn */ function from_method($class, $method = null) { // Supports: // - `$class = ['class', 'method'], $method = null // - `$class = [$object, 'method'], $method = null // - `$class = 'class', $method = 'method' // - `$class = $object, $method = 'method' if (!$method) { if (is_array($class) && count($class) === 2) { list($class, $method) = $class; } else { throw new IAE('Expected method name to be provided.'); } } list($class, $object) = determine_subject($class); if (!method_exists($object ?: $class, $method)) { throw new IAE('Expected the method to exist.'); } if ($object) { return scope(function (...$args) use ($object, $method) { return $object->{$method}(...$args); }, $object); } else { return scope(function (...$args) use ($class, $method) { return $class::{$method}(...$args); }, $class); } } /** * @param callable $fn * @return Fn */ function from_callable(callable $fn) { return $fn instanceof Fn ? $fn : function (...$args) use ($fn) { return $fn(...$args); }; } function determine_subject($class) { $object = null; if (is_object($class)) { $object = $class; $class = get_class($object); } elseif (!is_string($class)) { throw new IAE('Expected class name or object instance to be provided.'); } return [$class, $object]; } /** * Creates a partial application of a function. * * @param callable $fn * @param mixed[] $args * @return Fn */ function apply(callable $fn, ...$args) { return function (...$partialArgs) use ($fn, $args) { foreach ($args as &$arg) { if ($arg === SKIP) { $arg = array_shift($partialArgs); } } return $fn(...array_merge($args, $partialArgs)); }; } } namespace { class Five { private static $five = 5; private static function getFive() { return self::$five; } } $trimColons = fn\apply('trim', fn\SKIP, ':'); var_dump($trimColons(':foo:bar:')); $getFive = fn\from_method(Five::class, 'getFive'); var_dump($getFive()); } -
jeremeamia created this gist
Apr 19, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,119 @@ <?php namespace fn; use Closure as Fn; use InvalidArgumentException as IAE; const SKIP = "\0...\0"; /** * @param callable $fn * @param mixed $scope * @return Fn */ function scope(callable $fn, $scope) { $object = null; if (is_object($scope)) { $object = $scope; $scope = get_class($scope); } return closure($fn)->bindTo($object, $scope); } /** * @param string $function * @return Fn */ function func($function) { if (!is_string($function)) { throw new IAE('Expected the name of a function or static method.'); } if (strpos($function, '::') > 0) { return method_to_callable(...explode('::', $function, 2)); } if (!is_callable($function)) { throw new IAE('Expected the function to exist and be callable.'); } return closure($function); } /** * @param mixed $class * @param string|null $method * @return Fn */ function method($class, $method = null) { if (!$method && is_array($class) && count($class) === 2) { $object = null; list($class, $method) = $class; } elseif (is_string($class) && is_string($method)) { $object = null; } elseif (is_object($class) && is_string($method)) { $object = $class; $class = get_class($object); } else { throw new IAE('Expected a tuple containing a class name (or object instance) and method name.'); } $subject = $object ?: $class; if (!method_exists($subject, $method)) { throw new IAE('Expected the method to exist.'); } if ($object) { return scope(function (...$args) use ($object, $method) { return $object->{$method}(...$args); }, $object); } else { return scope(function (...$args) use ($class, $method) { return $class::{$method}(...$args); }, $class); } } /** * @param callable $fn * @return Fn */ function closure(callable $fn) { return $fn instanceof Fn ? $fn : function (...$args) use ($fn) { return $fn(...$args); }; } /** * Creates a partial application of a function. * * @param callable $fn * @param mixed[] $args * @return Fn */ function apply(callable $fn, ...$args) { return function (...$partialArgs) use ($fn, $args) { foreach ($args as &$arg) { if ($arg === SKIP) { $arg = array_shift($partialArgs); } } return $fn(...array_merge($args, $partialArgs)); }; } class Five { private static $five = 5; private static function getFive() { return self::$five; } } $trimColons = apply('trim', SKIP, ':'); var_dump($trimColons(':foo:bar:')); $getFive = method(Five::class, 'getFive'); var_dump($getFive());