При сопоставлении анонимной функции с анонимным массивом нет доступа к ключам:
array_map(
function($val) use ($foo) { /* ... */ },
array(key1 => val1,
key2 => val2,
/* ... */));
array_reduce также не получает доступ к ключам. array_walk может обращаться к ключам, но массив передается по ссылке, что требует уровня косвенности.
Некоторые решения:
Массив пар
Это плохо, так как мы меняем исходный массив. Кроме того, шаблонные вызовы "array ()" увеличиваются линейно с длиной массива:
array_map(
function($pair) use ($foo) {
list($key, $val) = $pair;
/* ... */
},
array(array(key1, val1),
array(key2, val2),
/* ... */));
Временная переменная
Мы работаем с исходным массивом, и шаблон постоянен, но мы можем легко забить существующую переменную:
$i_hope_this_does_not_conflict = array(key1 => val1,
key2 => val2,
/* ... */);
array_map(
function($key, $val) use ($foo) { /* ... */ },
array_keys($i_hope_this_does_not_conflict),
$i_hope_this_does_not_conflict);
unset($i_hope_this_does_not_conflict);
Функция однократного выстрела
Мы можем использовать область действия функции, чтобы предотвратить слипание существующих имен, но нам нужно добавить дополнительный слой «use»:
call_user_func(
function($arr) use ($foo) {
return array_map(function($key, $val) use ($foo) { /* ... */ },
array_keys($arr),
$arr);
},
array(key1 => val1,
key2 => val2,
/* ... */));
Функция одного аргумента с несколькими аргументами
Мы определяем отображаемую нами функцию в исходной области видимости, чтобы избежать использования шаблона):
call_user_func(
function($f, $arr) {
return array_map($f, array_keys($arr), $arr);
},
function($key, $val) use ($foo) { /* ... */ },
array(key1 => val1,
key2 => val2,
/* ... */));
Новая функция
Интересно отметить, что наша последняя однократная функция имеет приятную общую подпись и очень похожа на array_map. Возможно, мы захотим дать ему имя и использовать его повторно:
function array_mapk($f, $arr) {
return array_map($f, array_keys($arr), $arr);
}
Код нашего приложения становится:
array_mapk(
function($key, $val) use ($foo) { /* ... */ },
array(key1 => val1,
key2 => val2,
/* ... */));
Косвенная матрица Walk
При написании вышеупомянутого я игнорировал array_walk, так как он требует, чтобы его аргумент передавался по ссылке; однако с тех пор я понял, что это легко обойти, используя call_user_func. Я думаю, что это лучшая версия на данный момент:
call_user_func(
'array_walk',
array(key1 => val1,
key2 => val2,
/* ... */),
function($val, $key) use ($foo) { /* ... */ });