RE: [PHP] Re: unsetting a referenced parameter in a function
-Original Message- From: Shawn McKenzie [mailto:nos...@mckenzies.net] Sent: 23 July 2009 02:36 PM To: php-general@lists.php.net Subject: Re: [PHP] Re: unsetting a referenced parameter in a function Tom Worster wrote: > On 7/22/09 6:09 PM, "Shawn McKenzie" wrote: > >> Tom Worster wrote: >>> though the manual is perfectly clear that this should be expected, i >>> was a bit surprised that the result of the following is 42 >>> >>> >> function foo(&$a) { >>> $a = 42; >>> unset($a); >>> $a = 'meaning'; >>> } >>> foo($a); >>> print("$a\n"); >>> ?> >>> >>> normally i would expect unset() to free some memory. but in this >>> example it doesn't and has a different behavior: it releases foo's >>> reference to the global $a, allowing the next line to define a local $a. >>> >>> i think i'd have preferred compile error. >>> >>> >> Well, you unset the reference and then you assigned 'meaning' to a >> local function variable $a. Why would you get a compile error? > > when you state it in those terms (which are clearly correct) i wouldn't. > > but if the way i think is "unset() destroys the specified variables" > (as the manual puts it) then i expect that the specified variable > would be destroyed, not the reference. > > so, as i said, i was a bit surprised when the variable wasn't destroyed. > once i understood what was happening, i thought it a bit confusing to > have such scope-dependent differences in behavior of a language element. > > It might be easier to understand if you don't use the same var names: function foo(&$arg) { $arg = 42; unset($arg); $arg = 'meaning'; } $a = 0; foo($a); print("$a\n"); -Shawn -- Another way to see it (from Shawn's example): the "&" is an "address of" (reference to) a variable, so function foo(&$arg) creates a local variable $arg pointing to a global variable called $a. Changing the value of local $arg updates the global $a. The unset($arg) removes the local $arg but has no effect on global $a. The next line $arg = 'meaning' creates a new local variable called $arg which has no connection whatsoever with the $arg that was unset - it could just as well have been called $xyz. As Shawn pointed out there's no problem here with scope, you were just confusing yourself by using the same variable name in the function, but it's a separate local variable regardless of what name you give it. A slight variation of your example: You get exactly the same result as your example, for the same reason, the only difference is that you obviously can't change the local variable name in the function. A final variation (to drive the point home): function foo(&$arg) { global $a; $a = 42;<== at this point $arg = 42 unset($a); $a = 'meaning'; <== $arg is still 42 $a = &$arg; <== $a now points to same address $arg is pointing to $a = 'of life'; <== $arg now = 'of life' } $a = 0; foo($a); print("$a\n"); <== prints 'of life' Here in function foo() local $arg and local $a are both pointing to the global $a, and changing either of them changes the other (and changes the global variable). After unset($a) only local $arg is pointing to global $a. After $a = &$arg both local variables are again pointing to global $a, and local $a value has therefor obviously changed from 'meaning' to 42. Then after $a = 'of life' both local variables and the global $a is changed to 'of life'. Local $a and global $a have the same names but are different variables. Also, the local $a after unset($a) happens to have the same name as the $a before unset($a) but it's a different variable, it could just as easily been called $b after unset($a). A final point: the "global $a;" in the function doesn't mean it's THE global $a, it just means it's a local variable called $a pointing to (referencing) a global variable with the same name. In PHP it has to be the same name because that's the way the "global" statement works, but it can sometimes create the impression that it's the same variable. Hope I haven't made that as clear as mud. Cheers Arno -- -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Re: unsetting a referenced parameter in a function
I think he is confusing the "unset" semantic. Unset just destroy a variable, but not the content of it. Take a look at the output of this simple script: function avoid_global_scope() { $a = 'foo'; var_dump( get_defined_vars() ); $b =& $a; var_dump( get_defined_vars() ); unset( $a ); var_dump( get_defined_vars() ); unset( $b ); } avoid_global_scope(); This is the output in my apache2 / php 5.2.6... but yours MUST be the same array(1) { ["a"]=> string(3) "foo" } array(2) { ["a"]=> &string(3) "foo" ["b"]=> &string(3) "foo" } array(1) { ["b"]=> string(3) "foo" } Note in the second array both variables was converted to references. But in the third "b" is just a common variable. This behaviour is cause by how PHP handles the references? 1) $a = 'foo'; Here we have an string 'foo' and a variable "a" which points to the string. 2) $b =& $a; Now we have anothe variable "b" which refers to _contents_ of variable "a" Variable "a" is converted to a reference to it contents 3) unset( $a ); When "a" is destroyed only "b" refers to 'foo', PHP handles "b" as a common var 3) unset( $b ); When "b" is destroyed PHP notes that no one is referencing 'foo'... so, it's removed too. Remember... unset destroy variables, not it's content. class Foo { public static $last; function __construct() { self::$last =& $this; } } $a = new Foo; $a = null; unset( $a ); var_dump( Foo::$last instanceof Foo ); # bool(true) On Thu, Jul 23, 2009 at 9:35 AM, Shawn McKenzie wrote: > Tom Worster wrote: > > On 7/22/09 6:09 PM, "Shawn McKenzie" wrote: > > > >> Tom Worster wrote: > >>> though the manual is perfectly clear that this should be expected, i > was a > >>> bit surprised that the result of the following is 42 > >>> > >>> >>> function foo(&$a) { > >>> $a = 42; > >>> unset($a); > >>> $a = 'meaning'; > >>> } > >>> foo($a); > >>> print("$a\n"); > >>> ?> > >>> > >>> normally i would expect unset() to free some memory. but in this > example it > >>> doesn't and has a different behavior: it releases foo's reference to > the > >>> global $a, allowing the next line to define a local $a. > >>> > >>> i think i'd have preferred compile error. > >>> > >>> > >> Well, you unset the reference and then you assigned 'meaning' to a local > >> function variable $a. Why would you get a compile error? > > > > when you state it in those terms (which are clearly correct) i wouldn't. > > > > but if the way i think is "unset() destroys the specified variables" (as > the > > manual puts it) then i expect that the specified variable would be > > destroyed, not the reference. > > > > so, as i said, i was a bit surprised when the variable wasn't destroyed. > > once i understood what was happening, i thought it a bit confusing to > have > > such scope-dependent differences in behavior of a language element. > > > > > It might be easier to understand if you don't use the same var names: > > function foo(&$arg) { > $arg = 42; > unset($arg); > $arg = 'meaning'; > } > > $a = 0; > foo($a); > print("$a\n"); > > > -- > Thanks! > -Shawn > http://www.spidean.com > > -- > PHP General Mailing List (http://www.php.net/) > To unsubscribe, visit: http://www.php.net/unsub.php > > -- Martin Scotta
Re: [PHP] Re: unsetting a referenced parameter in a function
Tom Worster wrote: > On 7/22/09 6:09 PM, "Shawn McKenzie" wrote: > >> Tom Worster wrote: >>> though the manual is perfectly clear that this should be expected, i was a >>> bit surprised that the result of the following is 42 >>> >>> >> function foo(&$a) { >>> $a = 42; >>> unset($a); >>> $a = 'meaning'; >>> } >>> foo($a); >>> print("$a\n"); >>> ?> >>> >>> normally i would expect unset() to free some memory. but in this example it >>> doesn't and has a different behavior: it releases foo's reference to the >>> global $a, allowing the next line to define a local $a. >>> >>> i think i'd have preferred compile error. >>> >>> >> Well, you unset the reference and then you assigned 'meaning' to a local >> function variable $a. Why would you get a compile error? > > when you state it in those terms (which are clearly correct) i wouldn't. > > but if the way i think is "unset() destroys the specified variables" (as the > manual puts it) then i expect that the specified variable would be > destroyed, not the reference. > > so, as i said, i was a bit surprised when the variable wasn't destroyed. > once i understood what was happening, i thought it a bit confusing to have > such scope-dependent differences in behavior of a language element. > > It might be easier to understand if you don't use the same var names: function foo(&$arg) { $arg = 42; unset($arg); $arg = 'meaning'; } $a = 0; foo($a); print("$a\n"); -- Thanks! -Shawn http://www.spidean.com -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Re: unsetting a referenced parameter in a function
On Wed, Jul 22, 2009 at 9:27 PM, Tom Worster wrote: > On 7/22/09 6:09 PM, "Shawn McKenzie" wrote: > > > Tom Worster wrote: > >> though the manual is perfectly clear that this should be expected, i was > a > >> bit surprised that the result of the following is 42 > >> > >> >> function foo(&$a) { > >> $a = 42; > >> unset($a); > >> $a = 'meaning'; > >> } > >> foo($a); > >> print("$a\n"); > >> ?> > >> > >> normally i would expect unset() to free some memory. but in this example > it > >> doesn't and has a different behavior: it releases foo's reference to the > >> global $a, allowing the next line to define a local $a. > >> > >> i think i'd have preferred compile error. > >> > >> > > > > Well, you unset the reference and then you assigned 'meaning' to a local > > function variable $a. Why would you get a compile error? > > when you state it in those terms (which are clearly correct) i wouldn't. > > but if the way i think is "unset() destroys the specified variables" (as > the > manual puts it) then i expect that the specified variable would be > destroyed, not the reference. > > so, as i said, i was a bit surprised when the variable wasn't destroyed. > once i understood what was happening, i thought it a bit confusing to have > such scope-dependent differences in behavior of a language element. > > > > -- > PHP General Mailing List (http://www.php.net/) > To unsubscribe, visit: http://www.php.net/unsub.php > > RTM: http://php.net/unset The behavior of *unset()* inside of a function can vary depending on what type of variable you are attempting to destroy. If a globalized variable is *unset()* inside of a function, only the local variable is destroyed. The variable in the calling environment will retain the same value as before *unset()* was called. / ... / If a variable that is PASSED BY REFERENCE is *unset()* inside of a function, only the local variable is destroyed. The variable in the calling environment will retain the same value as before *unset()* was called. I think the manual is very clear about unset. -- Martin Scotta
Re: [PHP] Re: unsetting a referenced parameter in a function
On 7/22/09 6:09 PM, "Shawn McKenzie" wrote: > Tom Worster wrote: >> though the manual is perfectly clear that this should be expected, i was a >> bit surprised that the result of the following is 42 >> >> > function foo(&$a) { >> $a = 42; >> unset($a); >> $a = 'meaning'; >> } >> foo($a); >> print("$a\n"); >> ?> >> >> normally i would expect unset() to free some memory. but in this example it >> doesn't and has a different behavior: it releases foo's reference to the >> global $a, allowing the next line to define a local $a. >> >> i think i'd have preferred compile error. >> >> > > Well, you unset the reference and then you assigned 'meaning' to a local > function variable $a. Why would you get a compile error? when you state it in those terms (which are clearly correct) i wouldn't. but if the way i think is "unset() destroys the specified variables" (as the manual puts it) then i expect that the specified variable would be destroyed, not the reference. so, as i said, i was a bit surprised when the variable wasn't destroyed. once i understood what was happening, i thought it a bit confusing to have such scope-dependent differences in behavior of a language element. -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php