Passing functions to function by reference

php.internals

Brian Moon

20 years ago
In PHP4, you could do: function test() { return array(1,2,3); } $var = array_shift(test()); PHP 5.0 broke this. There was a fatal error on the array_shift that only variables could be passed by reference. There was a good argument for it. So, we started migrating our code. Well, seems this works in 5.1. So, my question is, was it an intentional "fix" or will this break again and we need to continue to watch for this? Brian.

Rasmus Lerdorf

20 years ago
Brian Moon wrote:
> In PHP4, you could do: > > function test() > { > return array(1,2,3); > } > > $var = array_shift(test()); > > PHP 5.0 broke this. There was a fatal error on the array_shift that > only variables could be passed by reference. There was a good argument > for it. So, we started migrating our code. > > Well, seems this works in 5.1. So, my question is, was it an > intentional "fix" or will this break again and we need to continue to > watch for this?
In 5.1 this now throws an E_STRICT instead of a warning. It is still a bad idea to pass a tempvar by reference, so yes, you should strive to write E_STRICT clean code. -Rasmus

Jason Garber

20 years ago
Hello Rasmus, RL> In 5.1 this now throws an E_STRICT instead of a warning. It is still a RL> bad idea to pass a tempvar by reference, so yes, you should strive to RL> write E_STRICT clean code. At the possible expense of being blamed and flamed, I'll say it... ifsetor($var, 'default') would go a long way to accommodate E_STRICT code.
-- Best regards, Jason mailto:jason@ionzoft.com Wednesday, April 26, 2006, 6:41:26 PM, you wrote: RL> Brian Moon wrote: >> In PHP4, you could do: >> >> function test() >> { >> return array(1,2,3); >> } >> >> $var = array_shift(test()); >> >> PHP 5.0 broke this. There was a fatal error on the array_shift that >> only variables could be passed by reference. There was a good argument >> for it. So, we started migrating our code. >> >> Well, seems this works in 5.1. So, my question is, was it an >> intentional "fix" or will this break again and we need to continue to >> watch for this? RL> In 5.1 this now throws an E_STRICT instead of a warning. It is still a RL> bad idea to pass a tempvar by reference, so yes, you should strive to RL> write E_STRICT clean code. RL> -Rasmus

Brian Moon

20 years ago
> In 5.1 this now throws an E_STRICT instead of a warning. It is still a > bad idea to pass a tempvar by reference, so yes, you should strive to > write E_STRICT clean code.
Yeah, its more of a question of rewriting 6 years of PHP or not. We were half way done when we upgraded the dev machines to 5.1. Brian.

Brion Vibber

20 years ago
Rasmus Lerdorf wrote:
>> PHP 5.0 broke this. There was a fatal error on the array_shift that >> only variables could be passed by reference. There was a good >> argument for it. So, we started migrating our code. >> >> Well, seems this works in 5.1. So, my question is, was it an >> intentional "fix" or will this break again and we need to continue to >> watch for this? > > In 5.1 this now throws an E_STRICT instead of a warning. It is still a > bad idea to pass a tempvar by reference, so yes, you should strive to > write E_STRICT clean code.
Stupid question: why is it a bad idea? I would expect these to be equivalent for all intents and purposes: func_taking_reference(some_func()); and $temp = some_func(); func_taking_reference($temp); where $temp is never used again and quickly passes out of scope. Is there some reason that they are not considered equivalent, or that they cannot or should not be made equivalent? I seem to remember a reason being quoted for all these reference-related changes something like it can cause memory corruption. But that would appear to be an implementation bug, not an essential difficulty, as if it were really *memory corruption* I can't imagine it being turned back on in 5.1. :) -- brion vibber (brion @ pobox.com / brion @ wikimedia.org)

Petar Nedyalkov

20 years ago
On Thursday 27 April 2006 23:01, Brion Vibber wrote:
> Rasmus Lerdorf wrote: > >> PHP 5.0 broke this. There was a fatal error on the array_shift that > >> only variables could be passed by reference. There was a good > >> argument for it. So, we started migrating our code. > >> > >> Well, seems this works in 5.1. So, my question is, was it an > >> intentional "fix" or will this break again and we need to continue to > >> watch for this? > > > > In 5.1 this now throws an E_STRICT instead of a warning. It is still a > > bad idea to pass a tempvar by reference, so yes, you should strive to > > write E_STRICT clean code. > > Stupid question: why is it a bad idea?
Check the mailing-list archive - there was a long discussion on this topic some 4, 5 months ago.
> > I would expect these to be equivalent for all intents and purposes: > > func_taking_reference(some_func()); > > and > > $temp = some_func(); > func_taking_reference($temp); > > where $temp is never used again and quickly passes out of scope. > > Is there some reason that they are not considered equivalent, or that they > cannot or should not be made equivalent?
Yes, of course :-) Nothing happens by chance here.
> > I seem to remember a reason being quoted for all these reference-related > changes something like it can cause memory corruption. But that would > appear to be an implementation bug, not an essential difficulty, as if it > were really *memory corruption* I can't imagine it being turned back on in > 5.1. :) > > -- brion vibber (brion @ pobox.com / brion @ wikimedia.org)
-- Cyberly yours, Petar Nedyalkov Devoted Orbitel Fan :-) PGP ID: 7AE45436 PGP Public Key: http://bu.orbitel.bg/pgp/bu.asc PGP Fingerprint: 7923 8D52 B145 02E8 6F63 8BDA 2D3F 7C0B 7AE4 5436

Rasmus Lerdorf

20 years ago
Brion Vibber wrote:
> Rasmus Lerdorf wrote: >>> PHP 5.0 broke this. There was a fatal error on the array_shift that >>> only variables could be passed by reference. There was a good >>> argument for it. So, we started migrating our code. >>> >>> Well, seems this works in 5.1. So, my question is, was it an >>> intentional "fix" or will this break again and we need to continue to >>> watch for this? >> In 5.1 this now throws an E_STRICT instead of a warning. It is still a >> bad idea to pass a tempvar by reference, so yes, you should strive to >> write E_STRICT clean code. > > Stupid question: why is it a bad idea?
Well, the original reason was because it caused weird and wonderful memory corruption in PHP 4.3.x, so if your code is ever going to run on that version you really need to not do that. It also tends to be a bug. Most functions that take an argument by reference do so for a reason. There are of course exceptions to this as you have pointed out and in those cases assuming your code will never run under PHP 4.3.x it can be valid. I would still say it is a better idea to something like: func_taking_reference($quiet=some_func()); // throw away ref mod and document the fact that you are intentionally throwing away the reference modification that func_taking_reference is making. That way you avoid the E_STRICT and make it very clear what you are doing. You could make the same argument for using undefined variables. Often that indicates a bug so the E_NOTICE can be really helpful, but other times it just gets in the way. I don't think that means we should do away with the E_NOTICE on that and I also don't think it means you shouldn't try to write E_NOTICE clean code. -Rasmus

Peter Brodersen

20 years ago
On Thu, 27 Apr 2006 17:24:55 -0400, in php.internals rasmus@lerdorf.com (Rasmus Lerdorf) wrote:
>It also tends to be a bug. Most functions that take an argument by >reference do so for a reason. There are of course exceptions to this as >you have pointed out and in those cases assuming your code will never >run under PHP 4.3.x it can be valid. I would still say it is a better >idea to something like: > > func_taking_reference($quiet=some_func()); // throw away ref mod > >and document the fact that you are intentionally throwing away the >reference modification that func_taking_reference is making. That way >you avoid the E_STRICT and make it very clear what you are doing.
It seems like a lot of these problems showed up because people used array_shift(), array_pop() or other such functions as a shortcut of retrieving an element returned from a function. I agree with the changes, but it still seems like people (mis)use these functions because of lack of array operators (e.g. array(2,4,3)[1] ). I don't know if I would go that far to state that there is a demand for such operators (and the discussion has been going on here before). But if there is no (just as) simple way of doing it right users will do it in a bad way.
-- - Peter Brodersen

Etienne Kneuss

20 years ago
Hello, I don't see the point using func_taking_reference($quiet=some_func()); The expression $quiet=some_func() will not "return" $quiet itself. So its not an alternative to $quiet=some_func(); func_taking_reference($quiet); You don't avoid the E_STRICT here. Regards Rasmus Lerdorf a écrit :
> Brion Vibber wrote: >> Rasmus Lerdorf wrote: >>>> PHP 5.0 broke this. There was a fatal error on the array_shift that >>>> only variables could be passed by reference. There was a good >>>> argument for it. So, we started migrating our code. >>>> >>>> Well, seems this works in 5.1. So, my question is, was it an >>>> intentional "fix" or will this break again and we need to continue to >>>> watch for this? >>> In 5.1 this now throws an E_STRICT instead of a warning. It is still a >>> bad idea to pass a tempvar by reference, so yes, you should strive to >>> write E_STRICT clean code. >> >> Stupid question: why is it a bad idea? > > Well, the original reason was because it caused weird and wonderful > memory corruption in PHP 4.3.x, so if your code is ever going to run > on that version you really need to not do that. > > It also tends to be a bug. Most functions that take an argument by > reference do so for a reason. There are of course exceptions to this > as you have pointed out and in those cases assuming your code will > never run under PHP 4.3.x it can be valid. I would still say it is a > better idea to something like: > > func_taking_reference($quiet=some_func()); // throw away ref mod > > and document the fact that you are intentionally throwing away the > reference modification that func_taking_reference is making. That way > you avoid the E_STRICT and make it very clear what you are doing. > > You could make the same argument for using undefined variables. Often > that indicates a bug so the E_NOTICE can be really helpful, but other > times it just gets in the way. I don't think that means we should do > away with the E_NOTICE on that and I also don't think it means you > shouldn't try to write E_NOTICE clean code. > > -Rasmus >
-- Etienne Kneuss http://www.colder.ch/ colder@php.net