<commit_before><?php

namespace Vector\Core;

use Vector\Core\Exception\FunctionNotFoundException;

abstract class Module
{
    /**
     * This flag globally sets a module to append an underscore when it proxies a function
     * call through the __callStatic magic method. This is so that dumb PHP IDEs can keep up with
     * what we're throwing down and allow us to override @method tags in a class doc.
     *
     * When this flag is enabled, you MUST append an underscore (_) to every function you declare
     * on your module, or else it will not be found when accessing it through the magic __callStatic method.
     *
     * This flag only affects the internal naming of your functions. You still access your functions through
     * their un-appended name. E.g. you will still use Lambda::compose() or Lambda::using('compose').
     *
     * @var boolean
     */
    protected static $dirtyHackToEnableIDEAutocompletion = false;

    /**
     * A memoized cache of all the function requests fulfilled by this module
     * @var array
     */
    protected static $fulfillmentCache = [];

    /**
     * An array of function names to NOT curry when being fulfilled from the 'using' method
     * @var array
     */
    protected static $doNotCurry = ['curry'];

    /**
     * Alternative Module Loading
     *
     * By utilizing the __callStatic magic method to intercept static method calls, we can
     * proxy those calls off to the ::using() method of the module to make the functions in the
     * module act like standard static PHP methods. The result is a more natural way of calling
     * Vector functions that is more akin to native PHP.
     *
     * Invoking the function with no arguments results in a closure that is identical to
     * requesting the function through a ::using() call.
     *
     * ```
     * $increment = Math::add(1);
     * $increment(5); // 6
     *
     * $head = ArrayList::head();
     * $head([1, 2, 3]); // 1
     * ```
     *
     * @param  string $name Name of the function to call
     * @param  mixed  $args Arguments to pass to the function
     * @return mixed        Result of proxying off to the requested function
     */
    public static function __callStatic($name, $args)
    {
        return call_user_func_array(self::using($name), $args);
    }

    /**
     * Function Curry
     *
     * Given some callable f, curry it so that its arguments can be applied in chunks.
     * Functions fulfilled from a module's 'using' method are automatically passed
     * through this function, unless they are listed out in a particular module's
     * 'doNotCurry' list.
     *
     * ```
     * $myFunction = function($a, $b) {
     *     return $a + $b;
     * };
     *
     * $myCurriedFunction = $curry($myFunction);
     * $myCurriedFunction(1); // Callable
     * $myCurriedFunction(1)(1); // 2, PHP7 Only
     * ```
     *
     * @type (* -> *) -> (* -> *)
     *
     * @param  Callable $f           Function to curry
     * @param  array    $appliedArgs The arguments already applied to the curried function. This
     *                               argument is for internal use only.
     * @return Callable              The result of currying the original function.
     */
    protected static function curry(Callable $f, $appliedArgs = [])
    {
        if ($f instanceof \Closure) {
            $reflector = (new \ReflectionFunction($f));
        } else {
            $reflector = (new \ReflectionMethod($f[0], $f[1]));
        }

        // Count the number of arguments the function is asking for
        $arity = $reflector->getNumberOfParameters();

        // Then return a new function where we use the arguments already closed over,
        // and merge them with the arguments we get from the new function.
        return function(...$suppliedArgs) use ($f, $appliedArgs, $arity) {
            $args = array_merge($appliedArgs, $suppliedArgs);

            // If we have enough arguments, apply them to the internally curried function
            // closed over from the original function call.
            if (count($args) >= $arity)
                return call_user_func_array($f, $args);
            // Otherwise, recursively call curry again, passing in the arguments supplied
            // from this call
            else
                return self::curry($f, $args);
        };
    }

    /**
     * Module Loading
     *
     * Provided some function name, load that function into a callable from the definition.
     * The function is automatically curried unless it is listed in that module's doNotCurry list.
     * If `using` is passed multiple function names, they are returned in an array so they can be
     * split apart using PHP's internal `list` function.
     *
     * ```
     * $myFunc = MyModule::using('myFunc'); // Callable
     * list($foo, $bar) = MyModule::using('foo', 'bar'); // $foo = Callable, $bar = Callable
     * ```
     *
     * @type String -> (* -> *)
     *
     * @param  array    $requestedFunctions Variadic list of strings, function names to request
     * @return callable                     A single callable, or an array of callable representing
     *                                      the fulfilled request for functions from the module
     */<commit_msg>Reverting changes to functors for a new branch.<commit_after><?php

namespace Vector\Core;

use Vector\Core\Exception\FunctionNotFoundException;

abstract class Module
{
    /**
     * This flag globally sets a module to append an underscore when it proxies a function
     * call through the __callStatic magic method. This is so that dumb PHP IDEs can keep up with
     * what we're throwing down and allow us to override @method tags in a class doc.
     *
     * When this flag is enabled, you MUST append an underscore (_) to every function you declare
     * on your module, or else it will not be found when accessing it through the magic __callStatic method.
     *
     * This flag only affects the internal naming of your functions. You still access your functions through
     * their un-appended name. E.g. you will still use Lambda::compose() or Lambda::using('compose').
     *
     * @var boolean
     */
    protected static $dirtyHackToEnableIDEAutocompletion = false;

    /**
     * An array of functions on this module to memoize automatically
     * @var array
     */
    protected static $memoize = [];

    /**
     * A memoized cache of all the function requests fulfilled by this module
     * @var array
     */
    protected static $fulfillmentCache = [];

    /**
     * An array of function names to NOT curry when being fulfilled from the 'using' method
     * @var array
     */
    protected static $doNotCurry = ['curry'];

    /**
     * Alternative Module Loading
     *
     * By utilizing the __callStatic magic method to intercept static method calls, we can
     * proxy those calls off to the ::using() method of the module to make the functions in the
     * module act like standard static PHP methods. The result is a more natural way of calling
     * Vector functions that is more akin to native PHP.
     *
     * Invoking the function with no arguments results in a closure that is identical to
     * requesting the function through a ::using() call.
     *
     * ```
     * $increment = Math::add(1);
     * $increment(5); // 6
     *
     * $head = ArrayList::head();
     * $head([1, 2, 3]); // 1
     * ```
     *
     * @param  string $name Name of the function to call
     * @param  mixed  $args Arguments to pass to the function
     * @return mixed        Result of proxying off to the requested function
     */
    public static function __callStatic($name, $args)
    {
        return call_user_func_array(self::using($name), $args);
    }

    /**
     * Function Curry
     *
     * Given some callable f, curry it so that its arguments can be applied in chunks.
     * Functions fulfilled from a module's 'using' method are automatically passed
     * through this function, unless they are listed out in a particular module's
     * 'doNotCurry' list.
     *
     * ```
     * $myFunction = function($a, $b) {
     *     return $a + $b;
     * };
     *
     * $myCurriedFunction = $curry($myFunction);
     * $myCurriedFunction(1); // Callable
     * $myCurriedFunction(1)(1); // 2, PHP7 Only
     * ```
     *
     * @type (* -> *) -> (* -> *)
     *
     * @param  Callable $f           Function to curry
     * @param  array    $appliedArgs The arguments already applied to the curried function. This
     *                               argument is for internal use only.
     * @return Callable              The result of currying the original function.
     */
    protected static function curry(Callable $f, $appliedArgs = [])
    {
        // Curry a function of unknown arity
        return self::curryWithArity($f, self::getArity($f));
    }

    protected static function curryWithArity(Callable $f, $arity, $appliedArgs = [])
    {
        // Then return a new function where we use the arguments already closed over,
        // and merge them with the arguments we get from the new function.
        return function(...$suppliedArgs) use ($f, $appliedArgs, $arity) {
            $args = array_merge($appliedArgs, $suppliedArgs);

            // If we have enough arguments, apply them to the internally curried function
            // closed over from the original function call.
            if (count($args) >= $arity)
                return call_user_func_array($f, $args);
            // Otherwise, recursively call curry again, passing in the arguments supplied
            // from this call
            else
                return self::curry($f, $args);
        };
    }

    protected static function getArity(Callable $f)
    {
        if ($f instanceof \Closure) {
            $reflector = (new \ReflectionFunction($f));
        } else {
            $reflector = (new \ReflectionMethod($f[0], $f[1]));
        }

        // Count the number of arguments the function is asking for
        return $reflector->getNumberOfParameters();
    }

    /**
     * Module Loading
     *
     * Provided some function name, load that function into a callable from the definition.
     * The function is automatically curried unless it is listed in that module's doNotCurry list.
     * If `using` is passed multiple function names, they are returned in an array so they can be
     * split apart using PHP's internal `list` function.
     *
     * ```
     * $myFunc = MyModule::using('myFunc'); // Callable
     * list($foo, $bar) = MyModule::using('foo', 'bar'); // $foo = Callable, $bar = Callable
     * ```
     *
     * @type String -> (* -> *)
     *
     * @param  array    $requestedFunctions Variadic list of strings, function names to request
     * @return callable                     A single callable, or an array of callable representing
     *                                      the fulfilled request for functions from the module
     */
{'fraction_non_alphanumeric': 0.09254894851341552, 'fraction_numerical': 0.0025380710659898475, 'mean_word_length': 2.2469099470276634, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3667247', 'n_tokens_mistral': 2951, 'n_tokens_neox': 2853, 'n_words': 1193}