rfc:argument_unpacking
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:argument_unpacking [2013/08/30 19:08] – nikic | rfc:argument_unpacking [2017/09/22 13:28] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 2: | Line 2: | ||
* Date: 2013-08-30 | * Date: 2013-08-30 | ||
* Author: Nikita Popov < | * Author: Nikita Popov < | ||
- | * Status: | + | * Status: |
- | * Proposed for: PHP 5.6 | + | * Patch: https:// |
- | * Patch: https:// | + | |
* Mailing list discussion: http:// | * Mailing list discussion: http:// | ||
Line 40: | Line 39: | ||
</ | </ | ||
- | It's possible to use '' | + | It's possible to use '' |
<code php> | <code php> | ||
- | test(1, 2, ...[3, 4], 5, 6, ...[7, 8]); // [1, 2, 3, 4, 5, 6, 7, 8] | + | $args1 = [1, 2, 3]; |
+ | $args2 = [4, 5, 6]; | ||
+ | test(...$args1, ...$args2); // [1, 2, 3, 4, 5, 6] | ||
+ | test(1, 2, 3, ...$args2); | ||
+ | </ | ||
+ | |||
+ | However, it is not possible to use normal arguments after argument unpacking was used. Both of the following are invalid: | ||
+ | |||
+ | <code php> | ||
+ | test(...$args1, 4, 5, 6); | ||
+ | test(...$args1, | ||
</ | </ | ||
Line 71: | Line 80: | ||
<code php> | <code php> | ||
- | var_dump(1, 2, ...null, 3, 4); | + | var_dump(1, 2, ...null, |
// Warning: Only arrays and Traversables can be unpacked | // Warning: Only arrays and Traversables can be unpacked | ||
// int(1) int(2) int(3) int(4) | // int(1) int(2) int(3) int(4) | ||
Line 90: | Line 99: | ||
</ | </ | ||
- | By-reference passing will not work if the unpacked entity is a Traversable. Instead an exception | + | By-reference passing will not work if the unpacked entity is a Traversable. Instead an '' |
<code php> | <code php> | ||
test(...new ArrayIterator([1, | test(...new ArrayIterator([1, | ||
- | // Exception: Cannot pass by-reference argument 3 of test() by unpacking a Traversable | + | // Warning: Cannot pass by-reference argument 3 of test() by unpacking a Traversable, passing by-value instead |
</ | </ | ||
- | The reasons why this is not allowed | + | The reasons why we can't pass by-reference from a Traversable |
* It's not possible to determine the number of elements in a Traversable ahead of time. As such we can not know whether unpacking the Traversable will or will not hit a by-reference argument. | * It's not possible to determine the number of elements in a Traversable ahead of time. As such we can not know whether unpacking the Traversable will or will not hit a by-reference argument. | ||
* It's not possible to determine if a Traversable has support for by-reference iteration or if it will trigger an error if this is requested. | * It's not possible to determine if a Traversable has support for by-reference iteration or if it will trigger an error if this is requested. | ||
- | | + | |
- | An exception rather than an error is used here because | + | ==== String keys ==== |
+ | |||
+ | In order to ensure forward-compatibility with [[rfc: | ||
===== Backward Compatibility ===== | ===== Backward Compatibility ===== | ||
Line 145: | Line 156: | ||
Lastly, it seems that people naturally expect that this syntax is present if the variadics syntax is present. So if we implement variadics, it's probably best to include this as well. | Lastly, it seems that people naturally expect that this syntax is present if the variadics syntax is present. So if we implement variadics, it's probably best to include this as well. | ||
+ | |||
+ | ===== Examples ===== | ||
+ | |||
+ | The code samples in the " | ||
+ | |||
+ | ==== Extending variadic functions: forwarding ==== | ||
+ | |||
+ | The introduction already mentioned '' | ||
+ | |||
+ | One case where this occurs is when extending variadic functions: | ||
+ | |||
+ | <code php> | ||
+ | class MySqlWithLogging extends MySql { | ||
+ | protected $logger; | ||
+ | public function query($query, | ||
+ | $this-> | ||
+ | ' | ||
+ | $query, implode(', | ||
+ | ); | ||
+ | | ||
+ | return parent:: | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The above code sample extends the variadic '' | ||
+ | |||
+ | ==== Partial application: | ||
+ | |||
+ | Some people were wondering on what occasion you would ever want to unpack *two* arguments in one function call. An example of such a usage is " | ||
+ | |||
+ | If you are not familiar with the concept, partial application allows you to " | ||
+ | |||
+ | <code php> | ||
+ | $arrayToLower = bind(' | ||
+ | |||
+ | $arrayToLower([' | ||
+ | |||
+ | // The above $arrayToLower call resolves to: | ||
+ | // array_map(' | ||
+ | </ | ||
+ | |||
+ | This is a common functional paradigm, but rather rarely used in PHP. Anyway, an " | ||
+ | |||
+ | <code php> | ||
+ | function bind(callable $function) { | ||
+ | $boundArgs = array_slice(func_get_args(), | ||
+ | return function() use ($function, $boundArgs) { | ||
+ | return call_user_func_array( | ||
+ | $function, array_merge($boundArgs, | ||
+ | ); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | And the " | ||
+ | |||
+ | <code php> | ||
+ | function bind(callable $function, ...$boundArgs) { | ||
+ | return function(...$args) use($function, | ||
+ | return $function(...$boundArgs, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
===== Patch ===== | ===== Patch ===== | ||
- | The diff can be found here: https:// | + | The patch for this features is available as a PR: https:// |
+ | |||
+ | ===== Vote ===== | ||
+ | |||
+ | As this is a language change a two third majority is required. | ||
+ | |||
+ | Voting started 2013-12-21 and ended 2014-01-11. | ||
- | The patch is based off the variadics implementation, | + | <doodle title=" |
+ | * Yes | ||
+ | * No | ||
+ | </ | ||
===== Support in other languages ===== | ===== Support in other languages ===== |
rfc/argument_unpacking.1377889686.txt.gz · Last modified: 2017/09/22 13:28 (external edit)