src/Caller.php
public function call(
        $callable,
        array $arguments = [],
        array $objects = []
    ) {
        if (is_array($callable) && count($callable) === 2) {
            /*
             * [class, method]
             * [object, method]
             */
            $object = reset($callable);
            $method = end($callable);
            return $this->callMethod($object, $method, $arguments, $objects);
        } elseif (is_string($callable)) {
            /*
             * function
             * "class::method"
             * "class@method"
             * class has __invoke
             */
            if (function_exists($callable)) {
                $fnc = new \ReflectionFunction($callable);
                return $this->resolveAndCallReflection($fnc, null, $arguments, $objects);
            } elseif (preg_match('/^\s*([^:@]+)(::|@)([^\s]+)\s*$/', $callable, $matches)) {
                $class = $matches[1];
                $method = $matches[3];
                return $this->call([$class, $method], $arguments, $objects);
            } elseif ($this->container->has($callable)) {
                return $this->call($this->container->get($callable), $arguments, $objects);
            } elseif (class_exists($callable, true) && method_exists($callable, '__invoke')) {
                $obj = $this->construct($callable);
                return $this->call($obj, $arguments, $objects);
            } else {
                throw new \InvalidArgumentException("Not a callable");
            }
        } elseif (is_object($callable)) {
            /*
             * object has __invoke
             * Closure
             */
            if ($callable instanceof \Closure) {
                $fnc = new \ReflectionFunction($callable);
                return $this->resolveAndCallReflection($fnc, null, $arguments, $objects);
            } elseif (method_exists($callable, '__invoke')) {
                return $this->callMethod($callable, '__invoke', $arguments, $objects);
            } else {
                throw new \InvalidArgumentException("Not a callable");
            }
        } else {
            /*
             * for call __construct use $this->construct()
             */
            throw new \InvalidArgumentException("Not a callable");
        }
    }
public function call(
        $callable,
        array $arguments = [],
        array $objects = []
    ) {
        if (is_array($callable) && count($callable) === 2) {
            /*
             * [class, method]
             * [object, method]
             */
            $object = reset($callable);
            $method = end($callable);
            return $this->callMethod($object, $method, $arguments, $objects);
        } elseif (is_string($callable)) {
            /*
             * function
             * "class::method"
             * "class@method"
             * class has __invoke
             */
            if (function_exists($callable)) {
                $fnc = new \ReflectionFunction($callable);
                return $this->resolveAndCallReflection($fnc, null, $arguments, $objects);
            } elseif (preg_match('/^\s*([^:@]+)(::|@)([^\s]+)\s*$/', $callable, $matches)) {
                $class = $matches[1];
                $method = $matches[3];
                return $this->call([$class, $method], $arguments, $objects);
            } elseif ($this->container->has($callable)) {
                return $this->call($this->container->get($callable), $arguments, $objects);
            } elseif (class_exists($callable, true) && method_exists($callable, '__invoke')) {
                $obj = $this->construct($callable);
                return $this->call($obj, $arguments, $objects);
            } else {
                throw new \InvalidArgumentException("Not a callable");
            }
        } elseif (is_object($callable)) {
            /*
             * object has __invoke
             * Closure
             */
            if ($callable instanceof \Closure) {
                $fnc = new \ReflectionFunction($callable);
                return $this->resolveAndCallReflection($fnc, null, $arguments, $objects);
            } elseif (method_exists($callable, '__invoke')) {
                return $this->callMethod($callable, '__invoke', $arguments, $objects);
            } else {
                throw new \InvalidArgumentException("Not a callable");
            }
        } else {
            /*
             * for call __construct use $this->construct()
             */
            throw new \InvalidArgumentException("Not a callable");
        }
    }
[class, method]
[class has __callStatic, method]
[object, method]
[object has __call, method]
[object in container by name, method]
function
class has __invoke
object has __invoke
"class::method"
"class@method"
Closure

@param callable|object $callable  A callable
@param mixed[]         $arguments [1, 2, null for use named arguments, objects or container] or ['x'=>1, 'y'=>2]
@param object[]        $objects   Used to find dependencies via is_a()
@return mixed