Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:67651 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 85757 invoked from network); 8 Jun 2013 02:04:34 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 8 Jun 2013 02:04:34 -0000 Authentication-Results: pb1.pair.com header.from=theanomaly.is@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=theanomaly.is@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 74.125.82.48 as permitted sender) X-PHP-List-Original-Sender: theanomaly.is@gmail.com X-Host-Fingerprint: 74.125.82.48 mail-wg0-f48.google.com Received: from [74.125.82.48] ([74.125.82.48:50293] helo=mail-wg0-f48.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 98/78-33815-03192B15 for ; Fri, 07 Jun 2013 22:04:33 -0400 Received: by mail-wg0-f48.google.com with SMTP id f12so3545577wgh.15 for ; Fri, 07 Jun 2013 19:04:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type; bh=V2EaWRp89ihIxl81TTd+MD1Vzsenv09ACx7WDscopLE=; b=wGRBAcl8egLv8CHBjbW208Y6qQxU6EKgExDH5FheNHiwY3SZp6o7zOkJedG4JCA8F4 RU7T+kNqw+dIQns0obXPgCZMjGRRhdgtaAb6lnsojwYpUMQTPkyqE/TQ8/ZoL+CUUvZy 4BPd6lFIwx6LnQl9KvbZZkjUJY4i6Zq5+ejcUQ0syxbVIZD60Ll3DPr+tJHFqSL8e91A 0eFarb1CherDKlXCOmwTyAiikznJe4itQm/Qk+6hZvIEAbv+2lRTenyXIhLCTcBwt4zT 7YD6qwi2I69QIqu8xYW8/iFftrt0aL+KjSgNqm2W22UWtX0hY77BXCSNj6Jjmgr30cbQ 16kA== MIME-Version: 1.0 X-Received: by 10.194.119.195 with SMTP id kw3mr645445wjb.64.1370657069640; Fri, 07 Jun 2013 19:04:29 -0700 (PDT) Received: by 10.227.156.201 with HTTP; Fri, 7 Jun 2013 19:04:29 -0700 (PDT) Date: Fri, 7 Jun 2013 22:04:29 -0400 Message-ID: To: PHP Internals Content-Type: multipart/alternative; boundary=089e01228946beb18004de9af7a9 Subject: Proposal for new array_map function to pass in keys From: theanomaly.is@gmail.com (Sherif Ramadan) --089e01228946beb18004de9af7a9 Content-Type: text/plain; charset=ISO-8859-1 I'm proposing a new function similar to the implementation of array_map that allows us to apply a user-supplied callback to every element in the array with the addition of the callback being passed the key as well as the value of each element. Additionally, I would like to propose that the callback can modify both the key as well as the value by return an array where the key would be used to replace the existing key and the value would replace the existing value. Currently, getting the key into the callback is only possible with array_map by passing in a second array. Modifying both values (or applying the return value of the callback to both the key and the value) is not possible with array_map. Modifying the existing behavior of the function would cause BC breaks since there are probably a lot of people using code similar to the following: array_map('strlen', array('foo','bar','baz','quix')); Where strlen expects exactly one parameter and handing two arguments would cause it to implicitly return null and issue an E_WARNING with each iteration of array_map. To get both the key and the value into the callback you would have to do something like the following: array_map('my_callback', $array, array_keys($array)); Unfortunately, this has some performance and memory implications. PHP arrays carry a lot of overhead and a large enough array means we hand a copy of they array keys as an array to the function. This may be unnecessary with a slightly improved implementation. So instead we would have to have a new function like array_map_key (perhaps) that passes two arguments to the callback on each iteration (the key and the value of each element). This would make the following code possible... function my_call_back($key, $value) { return array($value, strlen($value)); } $array = str_word_count("PHP is lots of fun!"); $array = array_map_key('my_call_back', $array); The result would be the following array: array(5) { ["PHP"]=> int(3) ["is"]=> int(2) ["lots"]=> int(4) ["of"]=> int(2) ["fun"]=> int(3) } This demonstrates modifying both the key as well as the value by applying a user supplied callback function to each of the array's elements. This can also be done with the foreach construct, but the problem with foreach constructs is that they are not reusable. Since array_map takes a callback it's easy to reuse the callback function in various places to modify similar data structures. This is not so with foreach. It can be argued that we simply put the foreach loop into a function and reuse that, but there is a slight performance optimization with the implementation of array_map that foreach can't do and that's that array_map can iterate over all of the arrays supplied at once and more quickly than user space can do the iteration. It wouldn't be too hard to modify the implementation of array_map ( http://lxr.php.net/xref/PHP_5_5/ext/standard/array.c#4270) to pass in the key and be able to return a new array where both key/value pairs are applied by the callback given the existing implementation already accesses this information with each iteration (so there's no noticeable performance degradation). The only change would be in constructing the new return value to include the key from the return value instead of using the existing key. I would like to get everyone's thoughts on introducing such a function into PHP 5.NEXT (obviously I'm too late for 5.5). If there is a real need for this function out there and I'm not the only one that thinks this is useful I would be happy to draft an RFC and provide an implementation. Regards, Sherif I don't just make coffee around the office. Sometimes they let me write code! --089e01228946beb18004de9af7a9--