1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* This file is part of the Ariadne Component Library. |
4
|
|
|
* |
5
|
|
|
* (c) Muze <[email protected]> |
6
|
|
|
* |
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
8
|
|
|
* file that was distributed with this source code. |
9
|
|
|
*/ |
10
|
|
|
namespace arc; |
11
|
|
|
|
12
|
1 |
|
function singleton($f) { |
13
|
2 |
|
return function () use ($f) { |
14
|
2 |
|
static $result; |
15
|
2 |
|
if (null === $result) { |
16
|
2 |
|
if ( $f instanceof \Closure && isset($this) ) { |
|
|
|
|
17
|
|
|
$f = \Closure::bind($f, $this); |
|
|
|
|
18
|
|
|
} |
19
|
2 |
|
$result = $f(); |
20
|
|
|
} |
21
|
2 |
|
return $result; |
22
|
2 |
|
}; |
23
|
|
|
} |
24
|
|
|
|
25
|
1 |
|
function partial(callable $callable, $partialArgs, $defaultArgs=[] ) { |
26
|
4 |
|
$partialMerge = function($partialArgs, $addedArgs, $defaultArgs = []) |
27
|
|
|
{ |
28
|
4 |
|
end( $partialArgs ); |
29
|
4 |
|
$l = key( $partialArgs ); |
30
|
4 |
|
for ($i = 0; $i <= $l; $i++) { |
31
|
4 |
|
if (!array_key_exists($i, $partialArgs) && count($addedArgs)) { |
32
|
4 |
|
$partialArgs[ $i ] = array_shift( $addedArgs ); |
33
|
|
|
} |
34
|
|
|
} |
35
|
4 |
|
if (count($addedArgs)) { // there are $addedArgs left, so there should be no 'holes' in $partialArgs |
36
|
|
|
$partialArgs =array_merge( $partialArgs, $addedArgs ); |
37
|
|
|
} |
38
|
|
|
// fill any 'holes' in $partialArgs with entries from $defaultArgs |
39
|
4 |
|
$result = array_replace( $defaultArgs, $partialArgs ); |
40
|
4 |
|
ksort($result); |
41
|
|
|
|
42
|
4 |
|
return $result; |
43
|
4 |
|
}; |
44
|
|
|
|
45
|
4 |
|
return function() use ($callable, $partialArgs, $defaultArgs, $partialMerge) { |
46
|
4 |
|
if ( $callable instanceof \Closure && isset($this) ) { |
|
|
|
|
47
|
|
|
$callable = \Closure::bind($callable, $this); |
|
|
|
|
48
|
|
|
} |
49
|
4 |
|
return call_user_func_array( $callable, $partialMerge( $partialArgs, func_get_args(), $defaultArgs ) ); |
50
|
4 |
|
}; |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Class lambda |
55
|
|
|
* Experimental functionality, may be removed later, use at own risk. |
56
|
|
|
* @package arc |
57
|
|
|
*/ |
58
|
|
|
class lambda |
59
|
|
|
{ |
60
|
|
|
/** |
61
|
|
|
* Returns a function with the given arguments already entered or partially applied. |
62
|
|
|
* @param callable $callable The function to curry |
63
|
|
|
* @param array $partialArgs unlimited Optional arguments to curry the function with |
64
|
|
|
* @param array $defaultArgs optional default values |
65
|
|
|
* @return callable |
66
|
|
|
*/ |
67
|
4 |
|
public static function partial(callable $callable, $partialArgs, $defaultArgs = []) |
68
|
|
|
{ |
69
|
4 |
|
return partial($callable, $partialArgs, $defaultArgs); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Returns a function with named arguments. The peppered function accepts one argument - a named array of values |
75
|
|
|
* @param callable $callable The function or method to pepper |
76
|
|
|
* @param array $namedArgs Optional. The named arguments to pepper the function with, the order must be the order |
77
|
|
|
* in which the unpeppered function expects them. If not set, pepper will use Reflection to get them. |
78
|
|
|
* Format is [ 'argumentName' => 'defaultValue' ] |
79
|
|
|
* @return callable |
80
|
|
|
*/ |
81
|
2 |
|
public static function pepper(callable $callable, $namedArgs=null) |
82
|
|
|
{ |
83
|
2 |
|
if ( !is_array( $namedArgs ) ) { |
84
|
|
|
$ref = !is_array($callable) ? new \ReflectionFunction($callable) : new \ReflectionMethod($callable[0], $callable[1]); |
85
|
|
|
$namedArgs = []; |
86
|
|
|
foreach ($ref->getParameters() as $parameter) { |
87
|
|
|
$namedArgs[ $parameter->getName() ] = $parameter->getDefaultValue(); |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
91
|
2 |
|
return function ($otherArgs) use ($callable, $namedArgs) { |
92
|
2 |
|
$args = array_values( array_merge( $namedArgs, $otherArgs ) ); |
93
|
2 |
|
return call_user_func_array( $callable, $args ); |
94
|
2 |
|
}; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Returns a method that will generate and call the given function only once and return its result for every call. |
99
|
|
|
* The first call generates the result. Each subsequent call simply returns that same result. This allows you |
100
|
|
|
* to create in-context singletons for any kind of object. |
101
|
|
|
* <code> |
102
|
|
|
* $proto = \arc\lambda::prototype([ |
103
|
|
|
* 'getSingleton' => \arc\lambda::singleton( function () { |
104
|
|
|
* return new ComplexObject(); |
105
|
|
|
* }) |
106
|
|
|
* ]); |
107
|
|
|
* </code> |
108
|
|
|
* @param callable $f The function to generate the singleton. |
109
|
|
|
* @return mixed The singleton. |
110
|
|
|
*/ |
111
|
2 |
|
public static function singleton($f) |
112
|
|
|
{ |
113
|
2 |
|
return singleton($f); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
} |
117
|
|
|
|
This check looks for calls to
isset(...)
orempty()
on variables that are yet undefined. These calls will always produce the same result and can be removed.This is most likely caused by the renaming of a variable or the removal of a function/method parameter.