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

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Find out more about Webmentions.)