# [RFC] Syntax for variadic functions

- Thread: https://externals.io/message/68639
- Original archive: https://news-web.php.net/php.internals/68639
- Started by Nikita Popov on 2013-08-28T15:47:26+00:00
- Messages: 24
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #68639 — Nikita Popov — 2013-08-28T15:47:26+00:00

URL: https://externals.io/message/68639#68639

Hi internals!

I'd like to propose an RFC, which adds dedicated syntax for variadic
functions:

    https://wiki.php.net/rfc/variadics

Basically this allows declaring variadics directly in the function
signature, rather than fetching the arguments using `func_get_args()`.
Example:

    public function query($query, ...$params) { /* ... */ }

What are your thoughts on this?

Thanks,
Nikita

---

## #68640 — Lazare Inepologlou — 2013-08-28T16:18:14+00:00

URL: https://externals.io/message/68639#68640 · In reply to: #68639

2013/8/28 Nikita Popov <nikita.ppv@gmail.com>

> Hi internals!
>
> I'd like to propose an RFC, which adds dedicated syntax for variadic
> functions:
>
>     https://wiki.php.net/rfc/variadics
>
> Basically this allows declaring variadics directly in the function
> signature, rather than fetching the arguments using `func_get_args()`.
> Example:
>
>     public function query($query, ...$params) { /* ... */ }
>
> What are your thoughts on this?
>
>
+1, primarily because it makes the code self-documented.

However, I would like to hilight one shortcoming of variadic functions
(both with the old and with the proposed syntax): There is no way to call a
variadic function unless all the arguments are hard-coded.

I am extenting the example of the RFC:

class MySQL implements DB {
  public function query($query, ...$params) {
    // ...
  }
  public function query_and_log($query, ...$params) {
    // this will not work:
    $result = $this->query( $query, $params );
    log( $query );
    return $result;
  }
}

Not only this does not work, but there is no way to make it work without
modifying the original function. Would it be possible to extend the RFC
with new syntax that could cover cases like that as well? Maybe something
like that:

$result = $this->query( $query, ...$params );


Other than that, the RFC is very welcome.

Lazare INEPOLOGLOU
Ingénieur Logiciel






> Thanks,
> Nikita

---

## #68641 — Nikita Popov — 2013-08-28T16:20:34+00:00

URL: https://externals.io/message/68639#68641 · In reply to: #68640

On Wed, Aug 28, 2013 at 6:18 PM, Lazare Inepologlou <linepogl@gmail.com>wrote:

> Not only this does not work, but there is no way to make it work without
> modifying the original function. Would it be possible to extend the RFC
> with new syntax that could cover cases like that as well? Maybe something
> like that:
>
> $result = $this->query( $query, ...$params );
>

I will implement this, but in a separate RFC :) [Later today or tomorrow]

Nikita

---

## #68642 — Ivan Enderlin @ Hoa — 2013-08-28T16:32:26+00:00

URL: https://externals.io/message/68639#68642 · In reply to: #68639

> Hi internals!
Hi Nikita :-),


> I'd like to propose an RFC, which adds dedicated syntax for variadic
> functions:
>
>      https://wiki.php.net/rfc/variadics
>
> Basically this allows declaring variadics directly in the function
> signature, rather than fetching the arguments using `func_get_args()`.
> Example:
>
>      public function query($query, ...$params) { /* ... */ }
>
> What are your thoughts on this?
Huge +1!
So if we call query('foo'), $params is set to an empty array, right? 
Could it be possible to change this behavior? Would it be interesting? 
For example: public function query($query, ...$params = null).

Cheers.

-- 
Ivan Enderlin
Developer of Hoa
http://hoa-project.net/

PhD. student at DISC/Femto-ST (Vesontio) and INRIA (Cassis)
http://disc.univ-fcomte.fr/ and http://www.inria.fr/

Member of HTML and WebApps Working Group of W3C
http://w3.org/

---

## #68644 — Matthew Leverton — 2013-08-28T19:27:53+00:00

URL: https://externals.io/message/68639#68644 · In reply to: #68639

> Hi internals!
>
> I'd like to propose an RFC, which adds dedicated syntax for variadic
> functions:
> ...
>
> What are your thoughts on this?
>
I think it's great way to clean things up and add some subtle new
functionality, particularly with Lazare's follow-up proposal about
expanding an indexed array into arguments.

Would any functions get deprecated as a result of this? e.g., `func_get_args()`

I assume it's a syntax error to do function fn(...$foo, $bar) or
function fn(...$foo, ...$bar)

I assume that function fn($a, $b = null, ...$c) is possible, and the
only way to populate $c is to call fn with three or more parameters.

--
Matthew Leverton

---

## #68647 — Marc Bennewitz — 2013-08-28T20:12:33+00:00

URL: https://externals.io/message/68639#68647 · In reply to: #68644

Am 28.08.2013 21:27, schrieb Matthew Leverton:
> 
> > […]
> 
> Would any functions get deprecated as a result of this? e.g., `func_get_args()`
> 
> <snip>
> 

It's not a good idea to deprecate the function
func_get_args/func_num_args() because it is used in user land code to
detect if a function was called with a specific argument like the following:

function (&$argByRef = null) {
    if (func_num_args() > 1) {
        // do expensive stuff to set $argByRef
        $argByRef = true;
    }
    return false;
}

---

## #68649 — Nikita Popov — 2013-08-28T20:15:56+00:00

URL: https://externals.io/message/68639#68649 · In reply to: #68644

On Wed, Aug 28, 2013 at 9:27 PM, Matthew Leverton <leverton@gmail.com>wrote:

> Would any functions get deprecated as a result of this? e.g.,
> `func_get_args()`
>

Nope, `func_get_args()` etc stay. This is now mentioned in
https://wiki.php.net/rfc/variadics#userland.


> I assume it's a syntax error to do function fn(...$foo, $bar) or
> function fn(...$foo, ...$bar)
>

Correct. This is now mentioned in
https://wiki.php.net/rfc/variadics#syntactic_restrictions.


> I assume that function fn($a, $b = null, ...$c) is possible, and the
> only way to populate $c is to call fn with three or more parameters.
>

That's also correct :)

Nikita

---

## #68652 — Damian Wadley — 2013-08-28T21:01:31+00:00

URL: https://externals.io/message/68639#68652 · In reply to: #68649

How about having the ellipsis _after_ the variable? That then coincides
with phpDocumentor's recommended syntax of "$c,..." and it keeps any
typehint or & with the variable name ("array &$arr..." versus "array
&...$arr") and, honestly, I think that reads more easily.




> On Wed, Aug 28, 2013 at 9:27 PM, Matthew Leverton <leverton@gmail.com
> > […]
>
> > […]
>
> Nope, `func_get_args()` etc stay. This is now mentioned in
> https://wiki.php.net/rfc/variadics#userland.
>
>
> > […]
>
> Correct. This is now mentioned in
> https://wiki.php.net/rfc/variadics#syntactic_restrictions.
>
>
> > […]
>
> That's also correct :)
>
> Nikita

---

## #68653 — Nikita Popov — 2013-08-28T21:06:31+00:00

URL: https://externals.io/message/68639#68653 · In reply to: #68652

> How about having the ellipsis _after_ the variable? That then coincides
> with phpDocumentor's recommended syntax of "$c,..."
>

That syntax has it neither before nor after, because there is no parameter
name.

and it keeps any typehint or & with the variable name ("array &$arr..."
> versus "array &...$arr") and, honestly, I think that reads more easily.
>

Please see the https://wiki.php.net/rfc/variadics#choice_of_syntax section
of the RFC. Quoting: "With ref-modifier (&$args...) this does not show well
that the individual arguments are references, rather than $args itself.
With typehint (array $args...) it also looks like the typehint applies to
$args itself rather than all variadic arguments."

Thanks,
Nikita

---

## #68656 — Stas Malyshev — 2013-08-28T22:09:19+00:00

URL: https://externals.io/message/68639#68656 · In reply to: #68644

Hi!

I like the idea, the concept of capturing "rest of args" is pretty
common. But couldn't we in addition have `func_get_args()` be able to
receive an int argument that would produce "the rest" in an easier way
for those that prefer func_ger_args()?

I wonder if this makes harder to implement named argument in the future
- which I think we still need to be looking at - but so far doesn't look
like it presents any additional problem compared to `func_get_args()`.

For prototype checks, this:

    public function query($query, ...$params);
    public function query($query, $param = null, ...$params);

Should be compatible. Same with:

    public function query($query, ...$params);
    public function query($query);

functions should be able to ignore some arguments, especially ones that
are optional anyway. I also think this:

public function query($query, ...$params)
public function query(...$params)

should be legal too.

I think it should also be explicitly specified what $params is if there
is no arguments - null? false? array()? I'd probably prefer array as it
makes it easy to do something like:

public __construct(...$params) {
  foreach($params as $k => $v) { $this->$k = $v; }
}

but in any way it should be specified.

I didn't look at the implementation yet, so I'll add comments on that
later.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #68658 — Levi Morrison — 2013-08-28T23:40:33+00:00

URL: https://externals.io/message/68639#68658 · In reply to: #68656

>
> functions should be able to ignore some arguments, especially ones that
> are optional anyway.


This is not the current behavior, so why should we change it? See:

  1 <?php
  2
  3 interface TestInterface {
  4     function query($params = null);
  5 }
  6
  7 class TestImplementation implements TestInterface {
  8     function query() {
  9
 10     }
 11 }


Fatal error: Declaration of TestImplementation::query() must be compatible
with that of TestInterface::query() in
/Users/levijm/Projects/HighlightPHP/tmp.php on line 7

---

## #68659 — Stas Malyshev — 2013-08-28T23:45:28+00:00

URL: https://externals.io/message/68639#68659 · In reply to: #68658

Hi!

>     functions should be able to ignore some arguments, especially ones that
>     are optional anyway.
> 
> 
> This is not the current behavior, so why should we change it? See:

Because it makes no sense?

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #68678 — Patrick ALLAERT — 2013-08-29T11:10:46+00:00

URL: https://externals.io/message/68639#68678 · In reply to: #68639

2013/8/28 Nikita Popov <nikita.ppv@gmail.com>:
> Hi internals!
>
> I'd like to propose an RFC, which adds dedicated syntax for variadic
> functions:
>
>     https://wiki.php.net/rfc/variadics
>
> Basically this allows declaring variadics directly in the function
> signature, rather than fetching the arguments using `func_get_args()`.
> Example:
>
>     public function query($query, ...$params) { /* ... */ }
>
> What are your thoughts on this?
>
> Thanks,
> Nikita

Using the current variadic functions makes it possible to use 0 or N
arguments, e.g.:

function sum() {
    return array_sum(func_get_args());
}

echo sum(10, 5); // echoes 15
echo sum(); // echoes 0

I see nowhere in the RFC whether:

function sum(...$params) { /* */ }

Requires at minimum one argument or none.

I have the _feeling_ that you imply it's minimum one which I would
consider a bit inconsistent with the current "implementation".

Can you please clarify this Nikita?

Thanks

---

## #68681 — Nikita Popov — 2013-08-29T12:02:39+00:00

URL: https://externals.io/message/68639#68681 · In reply to: #68656

On Thu, Aug 29, 2013 at 12:09 AM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:

> Hi!
>
> I like the idea, the concept of capturing "rest of args" is pretty
> common. But couldn't we in addition have `func_get_args()` be able to
> receive an int argument that would produce "the rest" in an easier way
> for those that prefer func_ger_args()?
>

I would do that if this RFC doesn't pass, but I don't see much point doing
both things (syntax + extra arg). Are there any particular scenarios where
using `func_get_args()` would be preferable?


> For prototype checks, this:
>
>     public function query($query, ...$params);
>     public function query($query, $param = null, ...$params);
>
> Should be compatible.


It already is. Only requirement is that the typehint/by-ref-mode of
$param=null is compatible with the typehint/by-ref-mode of ...$params :)


> Same with:
>
>     public function query($query, ...$params);
>     public function query($query);
>
> functions should be able to ignore some arguments, especially ones that
> are optional anyway. I also think this:
>
> public function query($query, ...$params)
> public function query(...$params)
>
> should be legal too.
>

I would like to stay consistent with the normal PHP behavior here. PHP
currently doesn't allow leaving off (required or optional) parameters. I
created a separate thread regarding that issue:
http://markmail.org/message/ejgmqjnjnbmfnuzv If we decide to allow having
less parameters there, then I'll follow suit here as well.


> I think it should also be explicitly specified what $params is if there
> is no arguments - null? false? array()? I'd probably prefer array as it
> makes it easy to do something like:
>
> public __construct(...$params) {
>   foreach($params as $k => $v) { $this->$k = $v; }
> }
>
> but in any way it should be specified.
>

Now specified in
https://wiki.php.net/rfc/variadics#population_of_variadic_parameter: The
default is an empty array.

Thanks for the comments,
Nikita

---

## #68682 — Lester Caine — 2013-08-29T12:51:38+00:00

URL: https://externals.io/message/68639#68682 · In reply to: #68639

Nikita Popov wrote:
> I'd like to propose an RFC, which adds dedicated syntax for variadic
> functions:
>
>      https://wiki.php.net/rfc/variadics

I can remember in PHP4 days, passing parameters to the database as a string of 
variables was the norm. Then arrays came along and it was preferable to pass the 
query followed by an array of values. We could take the array and validate the 
data in a function, adding any missing values needed before processing the SQL. 
Going back to the cumbersum method of working just seems wrong? Surely we should 
be promoting a tidier method of working?

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #68686 — Bryan C. Geraghty — 2013-08-29T15:06:26+00:00

URL: https://externals.io/message/68639#68686 · In reply to: #68682

Lester's position seems unclear but I'll weigh-in. Having strict interfaces
and arguments means that the developer does not have to parse and validate
each parameter that is arbitrarily passed in. If anything, I would prefer to
see `func_get_args()` removed entirely. Now, I know that won't happen but I
don't think extending the associated functionality to be more vague is a
good choice.

-----Original Message-----
From: Lester Caine [mailto:lester@lsces.co.uk] 
Sent: Thursday, August 29, 2013 7:52 AM
To: PHP internals
Subject: Re: [PHP-DEV] [RFC] Syntax for variadic functions

Nikita Popov wrote:
> I'd like to propose an RFC, which adds dedicated syntax for variadic
> functions:
>
>      https://wiki.php.net/rfc/variadics

I can remember in PHP4 days, passing parameters to the database as a string
of variables was the norm. Then arrays came along and it was preferable to
pass the query followed by an array of values. We could take the array and
validate the data in a function, adding any missing values needed before
processing the SQL. 
Going back to the cumbersum method of working just seems wrong? Surely we
should be promoting a tidier method of working?

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #68759 — jbondc@openmv.com — 2013-08-30T20:34:30+00:00

URL: https://externals.io/message/68639#68759 · In reply to: #68639

> 
>     https://wiki.php.net/rfc/variadics 

Interesting idea, expanding on:

function log($message, ...$options) {}

It would seem convenient to allow ...$options to be passed as a key-value array of arguments as well:
function logA($message, ...$options[]) {  echo count($options); }

logA("foo"); // 0
logA("foo", 1, 2); // 2
logA("foo", array(1,2,3)); // 3

The difference here is that variadic options is declared as an optional array, it would not support a 'typehint' forcing all arguments to be of the same type.
It could be a way to support ~ named parameters

// requires at least 1 argument named as 'level'
function logB($message, ...$options['level']) {
   echo $options['level'] .' '. count($options);
}

logB("foo");                                    // fails: 'level' argument missing
logB("foo", 'notice');                   //notice 1
logB("foo", ['level' => 'notice']); // notice 1
logB("foo", 'notice', 'extra'); // notice 2
logB("foo", ['level' => 'notice'], 'extra'); // notice 2

// requires min 2 arguments
function logC($message, ...$options['level','priority']) {
   echo 'level:'. $options['level'];
   echo 'priority:'. $options['priority'];
}
logC("foo", "notice", 4);                                    
logC("foo", ['level' => 'notice', 'priority' => 4]);

That would remove the need for a "splat" or "scatter" operator. The declaration "...$options[]" would mean, I accept an array of arguments followed by extra arguments

---

## #68760 — Sebastian Krebs — 2013-08-30T21:34:43+00:00

URL: https://externals.io/message/68639#68760 · In reply to: #68759

2013/8/30 jbondc@openmv.com <jbondc@openmv.com>

> 
> > […]
>
> Interesting idea, expanding on:
>
> function log($message, ...$options) {}
>
> It would seem convenient to allow ...$options to be passed as a key-value
> array of arguments as well:
> function logA($message, ...$options[]) {  echo count($options); }
>
> logA("foo"); // 0
> logA("foo", 1, 2); // 2
> logA("foo", array(1,2,3)); // 3
>
> The difference here is that variadic options is declared as an optional
> array, it would not support a 'typehint' forcing all arguments to be of the
> same type.
> It could be a way to support ~ named parameters
>
> // requires at least 1 argument named as 'level'
> function logB($message, ...$options['level']) {
>    echo $options['level'] .' '. count($options);
> }
>
> logB("foo");                                    // fails: 'level' argument
> missing
> logB("foo", 'notice');                   //notice 1
> logB("foo", ['level' => 'notice']); // notice 1
> logB("foo", 'notice', 'extra'); // notice 2
> logB("foo", ['level' => 'notice'], 'extra'); // notice 2
>
> // requires min 2 arguments
> function logC($message, ...$options['level','priority']) {
>    echo 'level:'. $options['level'];
>    echo 'priority:'. $options['priority'];
> }
> logC("foo", "notice", 4);
> logC("foo", ['level' => 'notice', 'priority' => 4]);
>
> That would remove the need for a "splat" or "scatter" operator. The
> declaration "...$options[]" would mean, I accept an array of arguments
> followed by extra arguments
>

I'd recommend to use an object, or separate parameters instead. Thats not a
use-case for argument-lists.


Regards
Sebastian


>
>
> --
> 
> 
>
>


-- 
github.com/KingCrunch

---

## #69124 — Nikita Popov — 2013-09-14T11:04:03+00:00

URL: https://externals.io/message/68639#69124 · In reply to: #68639

> Hi internals!
>
> I'd like to propose an RFC, which adds dedicated syntax for variadic
> functions:
>
>     https://wiki.php.net/rfc/variadics
>
> Basically this allows declaring variadics directly in the function
> signature, rather than fetching the arguments using `func_get_args()`.
> Example:
>
>     public function query($query, ...$params) { /* ... */ }
>
> What are your thoughts on this?
>

I'd like to go forward with voting on this. Are there any issues that still
need to be resolved?

Nikita

---

## #69150 — Sara Golemon — 2013-09-16T19:02:52+00:00

URL: https://externals.io/message/68639#69150 · In reply to: #69124

>
>
> I'd like to go forward with voting on this. Are there any issues that still
> need to be resolved?
>
> Assuming the RFC as-is represents the current state, I'm +1 on all of it.

I'm not a fan of some of the proposed alterations which would translate
arrays (a la `call_user_func_array()`).  To clarify, the following output is
what I'd expect:
function f(...$args) {
  echo count($args);
}
f(1,2,3); // 3
f([1,2,3]); // 1

Not "3" in both cases.

-Sara

---

## #69151 — Nikita Popov — 2013-09-16T19:14:51+00:00

URL: https://externals.io/message/68639#69151 · In reply to: #69150

>
> > […]
>
> I'm not a fan of some of the proposed alterations which would translate
> arrays (a la `call_user_func_array()`).  To clarify, the following output is
> what I'd expect:
> function f(...$args) {
>   echo count($args);
> }
> f(1,2,3); // 3
> f([1,2,3]); // 1
>
> Not "3" in both cases.
>

Yes, that's the output you'll get. If it weren't the case it would be
impossible to define a function accepting multiple array arguments like
f([1, 2, 3], [4, 5, 6], [7, 8, 9]).

Nikita

---

## #69155 — Sara Golemon — 2013-09-16T20:35:45+00:00

URL: https://externals.io/message/68639#69155 · In reply to: #69151

> Assuming the RFC as-is represents the current state, I'm +1 on all of it.
> > […]
>
> Yes, that's the output you'll get. If it weren't the case it would be
> impossible to define a function accepting multiple array arguments like
> f([1, 2, 3], [4, 5, 6], [7, 8, 9]).
>
> Right, that was exactly the ambiguity I was unfond of.  Glad that was as I
hoped. Voted +1.

---

## #69156 — Zeev Suraski — 2013-09-16T20:51:40+00:00

URL: https://externals.io/message/68639#69156 · In reply to: #68681

> -----Original Message-----
> From: Nikita Popov [mailto:nikita.ppv@gmail.com]
> Sent: Thursday, August 29, 2013 3:03 PM
> To: Stas Malyshev
> Cc: PHP internals
> Subject: Re: [PHP-DEV] [RFC] Syntax for variadic functions
>
> On Thu, Aug 29, 2013 at 12:09 AM, Stas Malyshev
> <smalyshev@sugarcrm.com>wrote:
>
> > […]
>
> I would do that if this RFC doesn't pass, but I don't see much point
doing
> both things (syntax + extra arg). Are there any particular scenarios
where
> using `func_get_args()` would be preferable?

Admittedly I'm (very) late to the game, but admittedly #2 - I actually
just noticed this thread as it went up for a vote.
Personally I find Stas's direction preferable to introducing new semantics
- mainly because I think that with every new piece of syntax we make the
language a tad bit more complex no matter what.
Conversely, adding an optional argument to `func_get_args()` sticks with the
same spirit we've had for years regarding variadic functions, and arguably
is more versatile.  Assuming we implement a [, start[, end]] syntax
support, then you can more granularly split exactly the offsets you want -
in case you don't want all of them in one array (which would require a
call to `array_slice()` using the new syntax).  Before you jump and say it's
not such a common case - I agree - I said arguably :)

Zeev

---

## #69157 — Zeev Suraski — 2013-09-16T21:41:10+00:00

URL: https://externals.io/message/68639#69157

> -----Original Message-----
> From: Zeev Suraski [mailto:zeev@zend.com]
> Sent: Monday, September 16, 2013 11:52 PM
> To: 'Nikita Popov'; 'Stas Malyshev'
> Cc: 'PHP internals'
> Subject: RE: [PHP-DEV] [RFC] Syntax for variadic functions
>
> > […]
>
> Admittedly I'm (very) late to the game, but admittedly #2 - I actually
just
> noticed this thread as it went up for a vote.
> Personally I find Stas's direction preferable to introducing new
semantics -
> mainly because I think that with every new piece of syntax we make the
> language a tad bit more complex no matter what.
> Conversely, adding an optional argument to `func_get_args()` sticks with
the
> same spirit we've had for years regarding variadic functions, and
arguably is
> more versatile.  Assuming we implement a [, start[, end]] syntax
support,
> then you can more granularly split exactly the offsets you want - in
case you
> don't want all of them in one array (which would require a call to
> `array_slice()` using the new syntax).  Before you jump and say it's not
such a
> common case - I agree - I said arguably :)

After thinking about it some more I see more value in the 2nd feature of
this RFC - the ability to do pass by reference on variable argument lists
- than I initially realized, so I'm actually in favor of the RFC.

I'm still in favor of `func_get_args()` being updated with start/end
optional parameters though.

Zeev
