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
|
|
|
|
It seems like you are assigning to a variable which was imported through a
use
statement which was not imported by reference.For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.
Change not visible in outer-scope
Change visible in outer-scope