[php] PHP's array_map including keys

I see it's missing the obvious answer:

function array_map_assoc(){
    if(func_num_args() < 2) throw new \BadFuncionCallException('Missing parameters');

    $args = func_get_args();
    $callback = $args[0];

    if(!is_callable($callback)) throw new \InvalidArgumentException('First parameter musst be callable');

    $arrays = array_slice($args, 1);

    array_walk($arrays, function(&$a){
        $a = (array)$a;
        reset($a);
    });

    $results = array();
    $max_length = max(array_map('count', $arrays));

    $arrays = array_map(function($pole) use ($max_length){
        return array_pad($pole, $max_length, null);
    }, $arrays);

    for($i=0; $i < $max_length; $i++){
        $elements = array();
        foreach($arrays as &$v){
            $elements[] = each($v);
        }
        unset($v);

        $out = call_user_func_array($callback, $elements);

        if($out === null) continue;

        $val = isset($out[1]) ? $out[1] : null;

        if(isset($out[0])){
            $results[$out[0]] = $val;
        }else{
            $results[] = $val;
        }
    }

    return $results;
}

Works exactly like array_map. Almost.

Actually, it's not pure map as you know it from other languages. Php is very weird, so it requires some very weird user functions, for we don't want to unbreak our precisely broken worse is better approach.

Really, it's not actually map at all. Yet, it's still very useful.

  • First obvious difference from array_map, is that the callback takes outputs of each() from every input array instead of value alone. You can still iterate through more arrays at once.

  • Second difference is the way the key is handled after it's returned from callback; the return value from callback function should be array('new_key', 'new_value'). Keys can and will be changed, same keys can even cause previous value being overwritten, if same key was returned. This is not common map behavior, yet it allows you to rewrite keys.

  • Third weird thing is, if you omit key in return value (either by array(1 => 'value') or array(null, 'value')), new key is going to be assigned, as if $array[] = $value was used. That isn't map's common behavior either, yet it comes handy sometimes, I guess.

  • Fourth weird thing is, if callback function doesn't return a value, or returns null, the whole set of current keys and values is omitted from the output, it's simply skipped. This feature is totally unmappy, yet it would make this function excellent stunt double for array_filter_assoc, if there was such function.

  • If you omit second element (1 => ...) (the value part) in callback's return, null is used instead of real value.

  • Any other elements except those with keys 0 and 1 in callback's return are ignored.

  • And finally, if lambda returns any value except of null or array, it's treated as if both key and value were omitted, so:

    1. new key for element is assigned
    2. null is used as it's value
WARNING:
Bear in mind, that this last feature is just a residue of previous features and it is probably completely useless. Relying on this feature is highly discouraged, as this feature is going to be randomly deprecated and changed unexpectedly in future releases.

NOTE:
Unlike in array_map, all non-array parameters passed to array_map_assoc, with the exception of first callback parameter, are silently casted to arrays.

EXAMPLES:
// TODO: examples, anyone?