Last active
November 24, 2015 02:02
-
-
Save meglio/8691859 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Trait Lazy | |
* | |
* Allows for static and dynamic lazy initialization. | |
* NB. Include "use Lazy;" in every class you want this functionality, otherwise collision may happen if any of parents use Lazy. | |
* | |
* Example: | |
* | |
* class Test { | |
* use Lazy; | |
* | |
* // The name of the functions, i.e. 'x' and 'y', will be used as a key for the storage of initialized values | |
* | |
* function x() { return $this->lazy( function(){ return 'heavy-computation'; } ); } | |
* | |
* static function y() { return self::lazyStatic( function(){ return 'heavy-computation'; } ); } | |
* | |
* // Calculate lazily for every unique combination of $p1 and $p2 | |
* function f($p1, $p2) { return $this->lazy( function()use($p1, $p2){ return 'computation involving p1 and p2'; } ); } | |
* } | |
*/ | |
trait Lazy | |
{ | |
private $__lazilyInitialized = []; | |
private static $__lazilyInitializedStatic = []; | |
private static function __initializeLazily(&$storage, callable $initializer) | |
{ | |
# Function name which calls $this->lazy() or self::lazyStatic() | |
$key = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function']; | |
# Static variables of the $initializer closure | |
$params = (new ReflectionFunction($initializer))->getStaticVariables(); | |
if (!is_array($params)) | |
$params = []; | |
if ($paramsCount = count($params)) | |
$key .= ' :' . $paramsCount . ' ' . serialize($params); | |
if (!array_key_exists($key, $storage)) | |
{ | |
if (is_callable($initializer)) | |
$storage[$key] = call_user_func($initializer); | |
else | |
throw new RuntimeException('$initializer is not callable'); | |
} | |
return $storage[$key]; | |
} | |
/** | |
* @param callback $initializer | |
* @return mixed | |
*/ | |
protected function lazy(callable $initializer) | |
{ | |
return self::__initializeLazily($this->__lazilyInitialized, $initializer); | |
} | |
/** | |
* @param $initializer | |
* @return mixed | |
*/ | |
protected static function lazyStatic(callable $initializer) | |
{ | |
return self::__initializeLazily(self::$__lazilyInitializedStatic, $initializer); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment