3131 * @template TValue
3232 * @template-extends Array_<TKey,TValue>
3333 * @template-implements MapInterface<TKey,TValue>
34+ * @psalm-immutable
3435 */
3536abstract class Map extends Array_ implements MapInterface
3637{
38+ /**
39+ * @psalm-param array<TKey,TValue> $data
40+ */
41+ public function __construct (array $ data = [])
42+ {
43+ parent ::__construct ($ data );
44+ }
45+
3746 public function merge (...$ stack ): MapInterface
3847 {
3948 $ instance = clone $ this ;
@@ -46,15 +55,16 @@ public function merge(...$stack): MapInterface
4655
4756 public function sort (?callable $ callback = null ): MapInterface
4857 {
49- $ data = $ this ->data ;
5058 $ instance = clone $ this ;
59+ $ data = $ instance ->data ;
5160 if ($ callback === null ) {
5261 asort ($ data , SORT_NATURAL );
5362 $ instance ->data = $ data ;
5463
5564 return $ instance ;
5665 }
5766
67+ /** @psalm-suppress ImpureFunctionCall */
5868 uasort ($ data , $ callback );
5969 $ instance ->data = $ data ;
6070
@@ -63,13 +73,20 @@ public function sort(?callable $callback = null): MapInterface
6373
6474 public function diffKeys (MapInterface $ other , ?callable $ keyComparator = null ): MapInterface
6575 {
66- $ instance = clone $ this ;
67- $ otherData = $ other ->toNativeArray ();
76+ $ instance = clone $ this ;
77+ $ otherData = $ other ->toNativeArray ();
78+ $ keyComparator = $ keyComparator ?? $ this ->keyComparator ();
6879
69- /** @psalm-var array<TKey,TValue> $diff1 */
70- $ diff1 = array_diff_ukey ($ this ->data , $ otherData , $ keyComparator ?? $ this ->keyComparator ());
71- /** @psalm-var array<TKey,TValue> $diff2 */
72- $ diff2 = array_diff_ukey ($ otherData , $ this ->data , $ keyComparator ?? $ this ->keyComparator ());
80+ /**
81+ * @psalm-var array<TKey,TValue> $diff1
82+ * @psalm-suppress ImpureFunctionCall
83+ */
84+ $ diff1 = array_diff_ukey ($ instance ->data , $ otherData , $ keyComparator );
85+ /**
86+ * @psalm-var array<TKey,TValue> $diff2
87+ * @psalm-suppress ImpureFunctionCall
88+ */
89+ $ diff2 = array_diff_ukey ($ otherData , $ instance ->data , $ keyComparator );
7390 $ merged = array_merge (
7491 $ diff1 ,
7592 $ diff2
@@ -97,22 +114,22 @@ public function toOrderedList(?callable $sorter = null): OrderedListInterface
97114 }
98115
99116 $ data = $ this ->data ;
117+
118+ /** @psalm-suppress ImpureFunctionCall */
100119 usort ($ data , $ sorter );
101120
102121 return new GenericOrderedList ($ data );
103122 }
104123
105124 public function filter (callable $ callback ): MapInterface
106125 {
107- $ instance = clone $ this ;
108- $ instance ->data = array_filter ($ this ->data , $ callback , ARRAY_FILTER_USE_BOTH );
126+ $ instance = clone $ this ;
127+ /** @psalm-suppress ImpureFunctionCall */
128+ $ instance ->data = array_filter ($ instance ->data , $ callback , ARRAY_FILTER_USE_BOTH );
109129
110130 return $ instance ;
111131 }
112132
113- /**
114- * @psalm-mutation-free
115- */
116133 public function keys (): OrderedListInterface
117134 {
118135 $ keys = array_keys ($ this ->data );
@@ -128,9 +145,6 @@ public function put($key, $value): MapInterface
128145 return $ instance ;
129146 }
130147
131- /**
132- * @psalm-mutation-free
133- */
134148 public function get (string $ key )
135149 {
136150 if (! $ this ->has ($ key )) {
@@ -157,7 +171,10 @@ public function intersect(MapInterface $other, ?callable $valueComparator = null
157171 private function intersection (MapInterface $ other , ?callable $ valueComparator , ?callable $ keyComparator ): array
158172 {
159173 if ($ valueComparator && $ keyComparator ) {
160- /** @psalm-var array<TKey,TValue> $intersection */
174+ /**
175+ * @psalm-var array<TKey,TValue> $intersection
176+ * @psalm-suppress ImpureFunctionCall
177+ */
161178 $ intersection = array_uintersect_uassoc (
162179 $ this ->data ,
163180 $ other ->toNativeArray (),
@@ -169,7 +186,10 @@ private function intersection(MapInterface $other, ?callable $valueComparator, ?
169186 }
170187
171188 if ($ keyComparator ) {
172- /** @psalm-var array<TKey,TValue> $intersection */
189+ /**
190+ * @psalm-var array<TKey,TValue> $intersection
191+ * @psalm-suppress ImpureFunctionCall
192+ */
173193 $ intersection = array_intersect_ukey ($ this ->data , $ other ->toNativeArray (), $ keyComparator );
174194
175195 return $ intersection ;
@@ -179,7 +199,10 @@ private function intersection(MapInterface $other, ?callable $valueComparator, ?
179199 $ valueComparator = $ this ->valueComparator ();
180200 }
181201
182- /** @psalm-var array<TKey,TValue> $intersection */
202+ /**
203+ * @psalm-var array<TKey,TValue> $intersection
204+ * @psalm-suppress ImpureFunctionCall
205+ */
183206 $ intersection = array_uintersect ($ this ->data , $ other ->toNativeArray (), $ valueComparator );
184207
185208 return $ intersection ;
@@ -214,14 +237,20 @@ public function intersectUserAssoc(
214237
215238 public function diff (MapInterface $ other , ?callable $ valueComparator = null ): MapInterface
216239 {
217- /** @psalm-var array<TKey,TValue> $diff1 */
240+ /**
241+ * @psalm-var array<TKey,TValue> $diff1
242+ * @psalm-suppress ImpureFunctionCall
243+ */
218244 $ diff1 = array_udiff (
219245 $ this ->toNativeArray (),
220246 $ other ->toNativeArray (),
221247 $ valueComparator ?? $ this ->valueComparator ()
222248 );
223249
224- /** @psalm-var array<TKey,TValue> $diff2 */
250+ /**
251+ * @psalm-var array<TKey,TValue> $diff2
252+ * @psalm-suppress ImpureFunctionCall
253+ */
225254 $ diff2 = array_udiff (
226255 $ other ->toNativeArray (),
227256 $ this ->toNativeArray (),
@@ -263,12 +292,12 @@ public function removeElement($element): MapInterface
263292
264293 public function map (callable $ callback ): MapInterface
265294 {
266- return new GenericMap (array_map ($ callback , $ this ->data ));
295+ $ instance = clone $ this ;
296+
297+ /** @psalm-suppress ImpureFunctionCall */
298+ return new GenericMap (array_map ($ callback , $ instance ->data ));
267299 }
268300
269- /**
270- * @psalm-mutation-free
271- */
272301 public function has (string $ key ): bool
273302 {
274303 return array_key_exists ($ key , $ this ->data );
0 commit comments