About

User

You are logged in as Anonymous.

Want to log out?

PHP Fun - Variable Arguments Be Reference?

Earlier, this week, one of my co-workers was working on a personal project in which he wanted to use a function to set a variable number of parameters to zero.

[php]// he wanted this:
$a = 1; $b = 2; $c = 3;
set_to_zero($a, $b, $c);
echo "$a $b $c"; // prints "0 0 0";
?>[/php]

His first impulse was to use func_get_args(). But this wasn't working for him. Turns out function_get_args() returns a COPY of the arguments, and not a reference. The manual didn't lean either way or the other, so I updated it.

A few mails bounced around our internal developer's list. It seems that there's no non-hack way to do this.
Here's what we came up with:

[b]Non-Solution #1[/b]
[php]function set_array_to_zero(&$array)
{
foreach ($array AS $k => $v) {
$array[$k] = 0;
}
}
$a = 1; $b = 2; $c = 3;
set_array_to_zero(array(&$a, &$b, &$c));
echo "$a $b $c"; // prints "0 0 0";
?>[/php]
This WORKS, and is probably the most "proper" way to do this, but the semantics violate his original requirements.

A couple other non-semantic-repecting solutions were proposed (one using $obj = new StdClass;), but nothing that really worked the way he intended.

Here's one that seems pretty close, on the surface:
[b]Non-Solution #4[/b]
[php]function set_var_to_zero($var)
{
for ($i=0; $i $GLOBALS[func_get_arg($i)] = 0;
}
}
$a = 1; $b = 2; $c = 3;
set_var_to_zero('a', 'b', 'c');
echo "$a $b $c"; // prints "0 0 0";
?>[/php]

Sure, it breaks semantics, again, but there's another major problem -- scope:
[b]Non-Solution #5[/b]
[php]function set_var_to_zero($var)
{
for ($i=0; $i $GLOBALS[func_get_arg($i)] = 0;
}
}

function foo()
{
$a = 1; $b = 2; $c = 3;
set_var_to_zero('a', 'b', 'c');
echo "$a $b $c"; // actually prints "1 2 3";
}

$a = 4; $b = 5; $c = 6;
foo();
?>[/php]

Since there's no way to operate on an intermediate scope (only local symbols and global symbols), at least in a functional context, this approach is a dead end.

Finally, after sleeping on it, I came up with this:

[b]Non-Solution #16[/b]
[php]error_reporting(E_ALL);
define('STZ_MAX_ARGUMENTS', 1023);
$set_to_zero = create_function(
'&$a'. implode(',&$a', range(0, STZ_MAX_ARGUMENTS)),
'for ($i=0; $i <= STZ_MAX_ARGUMENTS; $i++) ${"a$i"} = 0;'
);
$a = 1; $b = 2; $c = 3;
@$set_to_zero($a, $b, $c);
echo "$a $b $c"; // prints "0 0 0";
?>[/php]

This ALMOST works -- I mean, it's REALLY close. The semantics are still a LITTLE off -- the $ I can live with. The @error_suppressor is also necessary, because it seems that it's not possible to pass default values to create_function(...) (try removing the @ -- you'll get (1024 - actual_number_of_arguments) error messages). There's also the issue of limiting the number of arguments to an arbitrary number. The way I see it, no developer should be working on > 1000 (actually, even that is entirely too many), anyway.

So, without resorting to eval / writing to a file + include, this is the best solution we could come up with.

Personally, I'd alter my requirements to go with the array-passing approach.

S


4 Responses to PHP Fun - Variable Arguments Be Reference?

  1. 12 Alan Knowles 2005-02-13 08:49

    Your friends got to much of your time to waste :)

    $a = $b = $c = $d = 0;

    is actually less typing, and works....

  2. 13 sam 2008-06-29 01:16

    Oh, thank you.

    Your solution on how to set variables to zero is amazing, and would surely be a useful one if only it were in response to something along the lines of "How do I set variables to zero" and not "How do I pass variable arguments by reference."

    Thanks again.

  3. 656 DynV 2008-09-19 09:40

    Great article thanks ! Boy that Alan Knowles is not a fast one ... :D

  4. 662 DynV 2008-09-19 09:49

    I'd like to mention that there's a small mistake in one of your functions which follows the correct version :

    function set_var_to_zero($var)
    {
    for ($i = 0; $i func_num_args(); $i++) {
    $GLOBALS[func_get_arg($i)] = 0;
    }
    }

Leave a Reply




Clicky Web Analytics