/** * 2016-10-29 * @param mixed[] $a * @return string */ function dfa_hashm(array $a) { return md5(dfa_hash($a)); }
/** * 2016-09-04 * Не используем решения типа такого: http://stackoverflow.com/a/34711505 * потому что они возвращают @see \Closure, и тогда кэшируемая функция становится переменной, * что неудобно (неунифицировано и засоряет глобальную область видимости переменными). * @param \Closure $f * Используем именно array $a = [], а не ...$a, * чтобы кэшируемая функция не перечисляла свои аргументы при передачи их сюда, * а просто вызывала @see func_get_args() * * 2016-11-01 * Будьте осторожны при передаче в функцию $f параметров посредством use: * эти параметры не будут участвовать в расчёте ключа кэша. * * @param mixed[] $a [optional] * @return mixed */ function dfcf(\Closure $f, array $a = []) { /** @var array(string => mixed) $c */ static $c = []; /** @var array(string => string) $b */ $b = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]; /** * 2016-09-04 * Когда мы кэшируем статический метод, то ключ «class» присутствует, * а когда функцию — то отсутствует: https://3v4l.org/ehu4O * Ради ускорения не используем свои функции dfa() и df_cc(). * * 2016-11-24 * Когда мы кэшируем статический метод, то значением ключа «class» является не вызванный класс, * а тот класс, где определён кэшируемый метод: https://3v4l.org/OM5sD * Поэтому все потомки класса с кэшированным методом будут разделять общий кэш. * Поэтому если Вы хотите, чтобы потомки имели индивидуальный кэш, * то учитывайте это при вызове dfcf. * Например, пишите не так: private static function sModule() {return dfcf(function() {return S::convention(static::class) ;});} * а так: private static function sModule() {return dfcf(function($c) {return S::convention($c) ;}, [static::class]);} * * У нас нет возможности вычислять имя вызвавшего нас класса автоматически: * как уже было сказано выше, debug_backtrace() возвращает только имя класса, где метод был объявлен, * а не вызванного класса. * А get_called_class() мы здесь не можем вызывать вовсе: * «Warning: get_called_class() called from outside a class» * https://3v4l.org/ioT7c */ /** @var string $k */ $k = (!isset($b['class']) ? null : $b['class'] . '::') . $b['function'] . (!$a ? null : dfa_hash($a)); // 2016-09-04 // https://3v4l.org/9cQOO return array_key_exists($k, $c) ? $c[$k] : ($c[$k] = call_user_func_array($f, $a)); }