Named Parameters

Currently an awesome RFC to introduce Named Parameters to PHP is in the voting phase. As I voted against this RFC and some people asked me about my reasoning I thought I share it here.

After this tweet I had some interesting conversations on and off twitter that made me think about my take on named parameters back and forth.

And as much as I like the idea of named parameters I still see one major issue in the currently proposed implementation: Changing Parameter names.

With Named Parameters the names I give my parameters suddenly move from a mere implementation detail to part of the contract that my API specifies.

On function names

That is the same that happens with my function name or my class name – with the difference that I knew about that beforehand. And – well, let’s be honest: Naming things is hard and at least I accidentally shipped a wrongly named function in a library. So when I realized that, I had to release a new version of the library that contained the following code:

function generateSum(int $a, int $b): int 
{ 
    return $a + $b; 
}

/** @deprecated Use generateSum instead */ 
function genreateSum(int $a, int $b): int 
{ 
    return generateSum($a, $b); 
}

Yeah. You guessed what had happened. My IDE didn’t tell me. But hey. I can circumvent the issue by generating a new function – now hopefully with the correct name – and mark the old one as deprecated. Problem solved. Messy, but yeah. I deserve it!

Changing Parameter Names

But how can I do the same when I want/need/have to change a parameter name? I at least couldn’t find a solution to that in the RFC.

Given this function signature:

function myFunc($param1, $parma2);

How can I change that in a stable way?

function myFunc($param1, $param2);

/** @deprecated Use myFunc($param1, $param2) */
function myFunc($param1, $parma2);

This will result in a Fatal error: Cannot redeclare myFunc()

And sadly something like this was not mentioned in the RFC

@@NamedParamAlias('parma2','param2')
function myFunc($param1, $param2);

This would allow a transparent name change of a parameter while still allowing to generate a deprecation notice so that calling code can update their references.

So this code could be called in either way now but the first one would also emmit a deprecation notice so that I can adapt my code.

myFunc(parma2: 2, param1: 3);
myFunc(param2: 2, param1: 3);

Yes. this opens up some more questions like: What happens if I want to rename the parameter again? (You do it and ad another alias) What if I want to rename the parameter to a name that was used for a different parameter before? (You don’t!!)

This, by the way would also allow to make renaming parameters during inheritance easier:

class parent {
    function myFunc($a, $b){}
}

class child extends parent {
    @@NamedParamAlias('a', 'c');
    @@NamedParamAlias('b', 'd');
    function myFunc($c, $d){}
}

/** @var $class parent
$class = new child();
$class->myFunc(a: 2, b: 4);

So as long as this RFC can not help me with deliberately renaming parts of my public API I feel not able to say “Yes” to it.

As the question is not whether we need to rename a part of a public API but when