add ref method with arity setting
This commit is contained in:
parent
0b58a4c620
commit
9e348d929c
@ -27,31 +27,54 @@ function predicate($predicate): Predicate
|
|||||||
case $predicate instanceof Predicate:
|
case $predicate instanceof Predicate:
|
||||||
return $predicate;
|
return $predicate;
|
||||||
case is_callable($predicate):
|
case is_callable($predicate):
|
||||||
return new ClosurePredicate(\Closure::fromCallable($predicate));
|
return new ClosurePredicate(closure($predicate));
|
||||||
default:
|
default:
|
||||||
throw new \InvalidArgumentException('$predicate is not valid predicate.');
|
throw new \InvalidArgumentException('$predicate is not valid predicate.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ref($callable)
|
function closure($callable)
|
||||||
{
|
{
|
||||||
if (is_array($callable)) {
|
switch (true) {
|
||||||
list($object, $method) = $callable;
|
case $callable instanceof \Closure:
|
||||||
$reflection = new \ReflectionObject($object);
|
return $callable;
|
||||||
$method = $reflection->getMethod($method);
|
|
||||||
|
|
||||||
if (!$method->isPublic()) {
|
case is_array($callable):
|
||||||
$class = debug_backtrace()[1]['class'] ?? null;
|
list($object, $method) = $callable;
|
||||||
|
$reflection = new \ReflectionObject($object);
|
||||||
|
$method = $reflection->getMethod($method);
|
||||||
|
|
||||||
if ($reflection->name !== $class) {
|
if (!$method->isPublic()) {
|
||||||
throw new NoAccessException(sprintf('Method "%s" can only be accessed from inside of object.', $method->name));
|
$backtrace = debug_backtrace();
|
||||||
|
foreach ($backtrace as $trace) {
|
||||||
|
if (isset($trace['class']) && $trace['class'] === $reflection->name) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((isset($trace['class']) && strpos($trace['class'], "Kadet\\Functional\\") !== 0)
|
||||||
|
|| ($trace['function'] && strpos($trace['function'], "Kadet\\Functional\\") !== 0)) {
|
||||||
|
throw new NoAccessException(sprintf('Method "%s" can only be accessed from inside of object.', $method->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return $method->getClosure($object);
|
return $method->getClosure($object);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return \Closure::fromCallable($callable);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return \Closure::fromCallable($callable);
|
function arify($callable, int $arity)
|
||||||
|
{
|
||||||
|
return function (...$args) use ($callable, $arity) {
|
||||||
|
return $callable(...array_slice($args, 0, $arity));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function ref($callable, ?int $arity = null) {
|
||||||
|
$closure = closure($callable);
|
||||||
|
return $arity !== null ? arify($callable, $arity) : $closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
function not($predicate)
|
function not($predicate)
|
||||||
@ -101,6 +124,10 @@ function repeat($times, callable $callback)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function identity($x) {
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callable $callable
|
* @param callable $callable
|
||||||
*
|
*
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use function Kadet\Functional\apply;
|
use function Kadet\Functional\apply;
|
||||||
|
use function Kadet\Functional\arify;
|
||||||
use function Kadet\Functional\ref;
|
use function Kadet\Functional\ref;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,8 +30,15 @@ class TestObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RandomTest extends \PHPUnit\Framework\TestCase
|
class ReferencingTest extends \PHPUnit\Framework\TestCase
|
||||||
{
|
{
|
||||||
|
public function testReferenceClosure()
|
||||||
|
{
|
||||||
|
$f = function () { };
|
||||||
|
|
||||||
|
$this->assertSame($f, ref($f));
|
||||||
|
}
|
||||||
|
|
||||||
public function testApplicationOfArrayNotation()
|
public function testApplicationOfArrayNotation()
|
||||||
{
|
{
|
||||||
$object = new TestObject();
|
$object = new TestObject();
|
||||||
@ -54,4 +62,32 @@ class RandomTest extends \PHPUnit\Framework\TestCase
|
|||||||
|
|
||||||
ref([$object, 'priv']);
|
ref([$object, 'priv']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSetFunctionArity()
|
||||||
|
{
|
||||||
|
$f = function (...$args) {
|
||||||
|
return count($args);
|
||||||
|
};
|
||||||
|
|
||||||
|
$f = arify($f, 2);
|
||||||
|
|
||||||
|
$this->assertSame(1, $f(1));
|
||||||
|
$this->assertSame(2, $f(1, 2));
|
||||||
|
$this->assertSame(2, $f(1, 2, 3));
|
||||||
|
$this->assertSame(2, $f(1, 2, 3, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testReferencingWithSpecificArity()
|
||||||
|
{
|
||||||
|
$f = function (...$args) {
|
||||||
|
return count($args);
|
||||||
|
};
|
||||||
|
|
||||||
|
$f = ref($f, 2);
|
||||||
|
|
||||||
|
$this->assertSame(1, $f(1));
|
||||||
|
$this->assertSame(2, $f(1, 2));
|
||||||
|
$this->assertSame(2, $f(1, 2, 3));
|
||||||
|
$this->assertSame(2, $f(1, 2, 3, 4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user