sammyk

Sammy Kaye Powers

Contents

PHP RFC: Allow a trailing comma in function calls

Introduction

Allowing a trailing comma in function calls will make it more convenient to append arguments in many contexts where it is common to call a function with lots of arguments; especially variadic functions.

Proposal

A trailing comma has been allowed in array syntax since forever-ever, and in grouped namespace syntax since PHP 7.2.

# Currently possible
use Foo\Bar\{
    Foo,
    Bar,
};
 
$foo = [
    'foo',
    'bar',
];

Allowing a trailing comma makes sense in these contexts as new values get appended frequently. There is another context wherein appending more values frequently happens: calling a variadic function.

unset(
    $foo,
    $bar,
    $baz,
);

Frequent Context Examples

A trailing comma in function calls make it crazy convient to invoke any function that takes variable arguments (i.e. using the splat operator ... or func_get_args().)

Unsetting variables

It is extremely common to send a list of two or more arguments to unset() to unset variables.

unset(
    $somethingIDontNeedAnymore,
    $anotherOneToKill,
    $letsMakeThisEasy,
);

Sending variables to a template engine

Another extremely common practice is to send a list of variables to a template engine concisely using compact().

echo $twig->render(
    'index.html',
    compact(
        'title',
        'body',
        'comments',
    )
);

Merging arrays

Invoking array_merge() is another great example of how a trailing comma makes values easier to append.

$newArray = array_merge(
    $arrayOne,
    $arrayTwo,
    ['foo', 'bar'],
);

Debugging all the things

When you're quickly debugging with var_dump(), it's nice to not have to worry about removing that dangling comma in order for your script to run.

var_dump(
    $whatIsInThere,
    $probablyABugInThisOne,
    $oneMoreToCheck,
);

i18n & l10n

Internationalization & localization often makes use of variadic functions such as sprintf() that usually expand and contract over time.

$en = 'A trailing %s makes %s a happy developer.';
$text = sprintf(
    $en,
    'comma',
    'Jane',
);

And so on...

This list of examples is not meant to be exhaustive, but you can see how allowing a trailing comma in function calls fits well within the existing trailing comma contexts (arrays & grouped namespaces).

Method & closure calls too

Method calls also adopt trailing comma functionality.

class Foo
{
  public function __construct(...$args) {
    //
  }
 
  public function bar(...$args) {
    //
  }
 
  public function __invoke(...$args) {
    //
  }
}
 
$foo = new Foo(
  'constructor',
  'bar',
);
 
$foo->bar(
  'method',
  'bar',
);
 
$foo(
  'invoke',
  'bar',
);

And closures too.

$bar = function(...$args) {
  //
};
 
$bar(
  'closure',
  'bar',
);

"Not really a function" functions as well

There are two language constructs that look like functions but aren't that will also allow a trailing comma: unset() (as mentioned before) and isset().

unset($foo, $bar,);
var_dump(isset($foo, $bar,));

Wait, didn't we just vote on this?

Yes, there was an RFC to add trailing commas to all list syntax in PHP 7.2. Unfortunately due to an oversight on my end, the vote for function calls and function declarations was combined into one vote so the vote failed (but just barely!)

I was contacted by many “no” voters saying that they would have voted “yes” for function calls, but “no” for function declarations. This RFC proposes allowing a trailing comma in function call syntax only.

We are allowed to put this feature up for vote again since the mandatory 6-month waiting period has passed since the last vote and this RFC targets a new major version of PHP.

Backward Incompatible Changes

None

Proposed PHP Version(s)

PHP 7.3

What's not allowed

Function declaration syntax will not change. This RFC targets function call syntax only.

# Parse error
function bar($a, $b,) {
    //
}

Free-standing commas are not allowed.

# Parse error
foo(,);

Multiple trailing commas & leading commas are not allowed.

# Parse error
foo('function', 'bar',,);
# Also parse error
foo(, 'function', 'bar');

Other things that could look like functions like yield & list() will go untouched and no other list syntax will be affected.

Patches and Tests

This patch, sans the tests, is a trivial three-line change in the parser.

See the diff on GitHub

The trailing comma is thrown out at the parser level so there's no runtime computations wasted.

Implementation

Votes

An option needs 2/3 votes to win

Allow a trailing comma in function calls (75% approved)
User Vote
ashnazg Yes
bishop Yes
bmajdak No
bwoebi No
colinodell Yes
danack Yes
daverandom Yes
derick No
dm No
emir Yes
fmargaine Yes
francois Yes
galvao Yes
heiglandreas Yes
jhdxr Yes
kalle Yes
kelunik Yes
laruence No
lbarnaud Yes
lcobucci Yes
leigh No
leszek Yes
levim No
lstrojny Yes
mariano Yes
mcmic Yes
mfonda Yes
nikic Yes
ocramius Yes
peehaa No
pmmaga No
pollita Yes
ramsey Yes
rogeriopradoj Yes
salathe No
sammyk Yes
stas Yes
trowski Yes
weierophinney Yes
yunosh Yes