RE: [PHP] Re: unsetting a referenced parameter in a function

2009-07-23 Thread Arno Kuhl
-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

2009-07-23 Thread Martin Scotta
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

2009-07-23 Thread Shawn McKenzie
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

2009-07-22 Thread Martin Scotta
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

2009-07-22 Thread Tom Worster
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