public static function mapDeep($function, $aOrV, $params = array(), $opts = array(), &$hist = array())
    {
        $opts = \array_merge(array(
            'callback_expects'  => 'scalar',    // 'scalar', 'array', 'both'
            'resource'  => false,               // whether or not to map or skip the type: resource
            'depth'     => 0,                   // @interal
        ), $opts);
        $callbackParams = $params;
        if (!\is_array($callbackParams)) {
            $callbackParams = !\is_null($callbackParams)
                ? array($callbackParams)
                : array();
        }
        $callbackParams = \array_merge(array($aOrV), $callbackParams);
        if (\is_array($aOrV)) {
            if (!$opts['depth']) {
                // check if we need to be on the look out for self-reference loop
                $str = \print_r($aOrV, true);
                // $this->isRecursive = $this->debug->isRecursive($aOrV);
                self::$isRecursive = \strpos($str, '*RECURSION*') !== false;
            }
            $opts['depth']++;
            if (\in_array($opts['callback_expects'], array('array','both'))) {
                $aOrV = \call_user_func_array($function, $callbackParams);
            }
            $hist[] = $aOrV;
            foreach ($aOrV as $k => $v) {
                if (self::$isRecursive && \in_array($v, $hist)) {
                    continue;   // recursion
                }
                // if (!$this->isRecursive || !$this->debug->isRecursive($v, $k)) {
                // }
                $aOrV[$k] = self::mapDeep($function, $v, $params, $opts, $hist);
            }
        } elseif (\is_resource($aOrV) && !$opts['resource']) {
        } elseif (\in_array($opts['callback_expects'], array('scalar','both'))) {
            $aOrV = \call_user_func_array($function, $callbackParams);
        }
        return $aOrV;
    }