[prev in list] [next in list] [prev in thread] [next in thread] 

List:       zend-engine2
Subject:    PLEASE ignore previous implicit $this-> posting!
From:       "Mike Scott" <mike () mikescommunity ! com>
Date:       2001-10-07 12:21:44
[Download RAW message or body]

Sorry everyone, I copied and pasted the wrong code into the previous email - profuse \
apologies for this blunder. Please ignore the previous posting. The following is how \
it should have looked, with the global example correct...

With all the discussion on namespaces, the chat about having class members
within the scope of class functions sort of stalled half way through. I'd
like to give it a kick start again.

I've read the objections to the idea of a "member" keyword that would drag
nominated class variables into the member function's scope by aliasing them.
I'm actually not in favour of this because I'd rather see identifiers
defined in enclosing scopes being visible implicitly anyway. But I noted
there may be performance issues and also difficulties with existing code,
hence I came up with the idea of "member" simply because we use an identical
technique for aliasing globals.

Now, if the necessity to alias globals is to be dropped in 2.0, then I would
raise the bar by suggesting that *ALL* variables and functions defined in
enclosing scopes are visible. This, to me, is much more logical. I've laid
out my reasoning step-by-step in the rest of this email. All examples are
functional so you can copy and paste them and run them. Note: they don't
output HTML - run them at the command line or replace '\n' with '<br>'.

Let's say we have a global variable and a couple of functions:

<?php

echo "Global scope example\n\n" ;

$MyVar = "global" ;

function One()
{
  // I want to access local $MyVar here...
  echo "var=$MyVar\n" ; // displays "var="

  // need to use "global" 
  global $MyVar ;
  echo "var=$MyVar\n" ; // displays "var=global"

  // but we COULD use the $GLOBALS array
  echo "var={$GLOBALS["MyVar"]}\n" ; // displays "var=global"
}

function Two()
{
  // One() is in scope
  One() ;
}

Two() ;
?>

Because the functions are global, they can call each other and thus they are 
visible from the enclosing scope. Similarly, $MyVar should be visible
within One() and Two() but in PHP 1.x it is not, and we have either to alias
it with the "global" keyword, or access the $GLOBALS array. I don't think
anyone does the latter.

PHP supports nesting of functions, but there's not really any point other
than keeping code together in one place in a file. Let's stick the above
into a big function and check for consistency:

<?php

echo "Nested function scope example\n\n" ;

$MyVar = "global" ;

function BigFunc()
{
  $MyVar = "local" ;

  function One()
  {
    // I want to access local $MyVar here... 
    // don't I can't!!
    // ... very inconsistent!
    echo "var=$MyVar\n" ; // displays "var="
    
    // "global" sees the global var not the local one
    global $MyVar ;
    echo "var=$MyVar\n" ; // displays "var=global"
  }

  function Two()
  {
    // One() is still in scope
    One() ;  
  }
  
  Two() ;
}

echo "calling BigFunc()\n" ;
BigFunc() ;

// can also call Two() here, even though it's in the 
// scope of BigFunc()!
echo "\ncalling Two() outside of BigFunc()\n" ;
Two() ;
?>

So here we have a case where the nested functions can't access peer
variables declared in the enclosing scope, but they can access peer
functions. However, although it looks like the functions are declared within
the scope of BigFunc() they are not - they're global and behave like they
were declared outside the enclosing function. Very strange! Because of this,
there's no way of accessing the local variables from the enclosing function.

Now, let's try a class:

<?php

echo "Class scope example\n\n" ;

$MyVar = "global" ;

class MyClass
{
  var $MyVar = "member" ;

  function One()
  {
    // I want to access member $MyVar here... 
    // don't have the equivalent of "global"
    echo "var=$MyVar\n" ; // displays "var="
    
    // have to use $this-> every time :-(
    // ... inconsistent!    
    echo "var=$this->MyVar\n" ; // displays "var=member"
  }

  function Two()
  {
    // One() is no longer in scope
    // need to use $this-> every time :-(
    // ... inconsistent
    $this->One() ;  
  }
}

$MyInstance = new MyClass ;
$MyInstance->Two() ;
?>

Since they're all peers $MyVar should be visible inside the functions but
again, in PHP 1.x it is not. Now, since this is an identical scenario to the
global one above except that we are up one level in scope, it seems to me
that to make things consistent we need an aliasing keyword analogous to
"global", hence my suggestion of "member". To all those who say we can use
"$this->", I say to access globals we can use the $GLOBALS array (although
we can as the first example shows) but we alias them with "global". So why
do this with globals and not members?

But all this is messy simply because of the fact that functions don't
inherit from enclosing scopes. IMO, this is a flaw in the PHP language and
has created the mess we're now in. So after all this reasoning, my proposal
boils down to either:

1. Inherit identifiers from enclosing scopes as other languages do.

OR

2. Make things consistent by adding an aliasing keyword such as "member".

I believe I've seen performance arguments against inheriting identifiers but
I've asked several times for details of this. If it's a performance issue,
why? It may be that there's a way of solving this by structuring the symbol
table differently.

Mike Scott.


[Attachment #3 (text/html)]

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 6.00.2600.0" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Arial size=2>Sorry everyone, I copied and pasted the wrong code 
into the previous email - profuse apologies for this blunder. Please ignore 
the&nbsp;previous posting.&nbsp;The following is how it should have looked, with 
the global example correct...</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV>With all the discussion on namespaces, the chat about having class 
members<BR>within the scope of class functions sort of stalled half way through. 
I'd<BR>like to give it a kick start again.<BR><BR>I've read the objections to 
the idea of a "member" keyword that would drag<BR>nominated class variables into 
the member function's scope by aliasing them.<BR>I'm actually not in favour of 
this because I'd rather see identifiers<BR>defined in enclosing scopes being 
visible implicitly anyway. But I noted<BR>there may be performance issues and 
also difficulties with existing code,<BR>hence I came up with the idea of 
"member" simply because we use an identical<BR>technique for aliasing 
globals.<BR><BR>Now, if the necessity to alias globals is to be dropped in 2.0, 
then I would<BR>raise the bar by suggesting that *ALL* variables and functions 
defined in<BR>enclosing scopes are visible. This, to me, is much more logical. 
I've laid<BR>out my reasoning step-by-step in the rest of this email. All 
examples are<BR>functional so you can copy and paste them and run them. Note: 
they don't<BR>output HTML - run them at the command line or replace '\n' with 
'&lt;br&gt;'.<BR><BR>Let's say we have a global variable and a couple of 
functions:<BR><BR><FONT face=Arial size=2>&lt;?php</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>echo "Global scope example\n\n" ;</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>$MyVar = "global" ;</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>function One()<BR>{<BR>&nbsp; // I want to access 
local $MyVar here...<BR>&nbsp; echo "var=$MyVar\n" ; // displays 
"var="</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp; // need to use "global" <BR>&nbsp; global 
$MyVar ;<BR>&nbsp; echo "var=$MyVar\n" ; // displays "var=global"</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp; // but we COULD use the $GLOBALS 
array<BR>&nbsp; echo "var={$GLOBALS["MyVar"]}\n" ; // displays 
"var=global"<BR>}</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>function Two()<BR>{<BR>&nbsp; // One() is in 
scope<BR>&nbsp; One() ;<BR>}</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Two() ;<BR>?&gt;<BR></FONT></DIV>
<DIV>Because the functions are global, they can call each other and thus they 
are </DIV>
<DIV>visible from the enclosing scope. Similarly, $MyVar should be 
visible<BR>within One() and Two() but in PHP 1.x it is not, and we have either 
to alias<BR>it with the "global" keyword, or access the $GLOBALS array. I don't 
think<BR>anyone does the latter.<BR><BR>PHP supports nesting of functions, but 
there's not really any point other<BR>than keeping code together in one place in 
a file. Let's stick the above<BR>into a big function and check for 
consistency:<BR><BR><FONT face=Arial size=2>&lt;?php</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>echo "Nested function scope example\n\n" 
;</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>$MyVar = "global" ;</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>function BigFunc()<BR>{<BR>&nbsp; $MyVar = "local" 
;</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp; function One()<BR>&nbsp; 
{<BR>&nbsp;&nbsp;&nbsp; // I want to access local $MyVar here... 
<BR>&nbsp;&nbsp;&nbsp; // don't I can't!!<BR>&nbsp;&nbsp;&nbsp; // ... very 
inconsistent!<BR>&nbsp;&nbsp;&nbsp; echo "var=$MyVar\n" ; // displays 
"var="<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; // "global" sees the global 
var not the local one<BR>&nbsp;&nbsp;&nbsp; global $MyVar 
;<BR>&nbsp;&nbsp;&nbsp; echo "var=$MyVar\n" ; // displays "var=global"<BR>&nbsp; 
}</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp; function Two()<BR>&nbsp; 
{<BR>&nbsp;&nbsp;&nbsp; // One() is still in scope<BR>&nbsp;&nbsp;&nbsp; One() 
;&nbsp; <BR>&nbsp; }<BR>&nbsp; <BR>&nbsp; Two() ;<BR>}</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>echo "calling BigFunc()\n" ;<BR>BigFunc() 
;</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>// can also call Two() here, even though it's in 
the <BR>// scope of BigFunc()!<BR>echo "\ncalling Two() outside of BigFunc()\n" 
;<BR>Two() ;</FONT></DIV>
<DIV><FONT face=Arial size=2>?&gt;</FONT></DIV><FONT face=Arial size=2></FONT>
<DIV><BR>So here we have a case where the nested functions can't access 
peer<BR>variables declared in the enclosing scope, but they can access 
peer<BR>functions. However, although it looks like the functions are declared 
within<BR>the scope of BigFunc() they are not - they're global and behave like 
they<BR>were declared outside the enclosing function. Very strange! Because of 
this,<BR>there's no way of accessing the local variables from the enclosing 
function.<BR><BR>Now, let's try a class:<BR><BR><FONT face=Arial 
size=2>&lt;?php</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>echo "Class scope example\n\n" ;</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>$MyVar = "global" ;</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>class MyClass<BR>{<BR>&nbsp; var $MyVar = "member" 
;</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp; function One()<BR>&nbsp; 
{<BR>&nbsp;&nbsp;&nbsp; // I want to access member $MyVar here... 
<BR>&nbsp;&nbsp;&nbsp; // don't have the equivalent of 
"global"<BR>&nbsp;&nbsp;&nbsp; echo "var=$MyVar\n" ; // displays 
"var="<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; // have to use $this-&gt; 
every time :-(<BR>&nbsp;&nbsp;&nbsp; // ... inconsistent!&nbsp;&nbsp;&nbsp; 
<BR>&nbsp;&nbsp;&nbsp; echo "var=$this-&gt;MyVar\n" ; // displays 
"var=member"<BR>&nbsp; }</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>&nbsp; function Two()<BR>&nbsp; 
{<BR>&nbsp;&nbsp;&nbsp; // One() is no longer in scope<BR>&nbsp;&nbsp;&nbsp; // 
need to use $this-&gt; every time :-(<BR>&nbsp;&nbsp;&nbsp; // ... 
inconsistent<BR>&nbsp;&nbsp;&nbsp; $this-&gt;One() ;&nbsp; <BR>&nbsp; 
}<BR>}</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>$MyInstance = new MyClass 
;<BR>$MyInstance-&gt;Two() ;<BR>?&gt;</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT><BR>Since they're all peers $MyVar should be 
visible inside the functions but<BR>again, in PHP 1.x it is not. Now, since this 
is an identical scenario to the<BR>global one above except that we are up one 
level in scope, it seems to me<BR>that to make things consistent we need an 
aliasing keyword analogous to<BR>"global", hence my suggestion of "member". To 
all those who say we can use<BR>"$this-&gt;", I say to access globals we can use 
the $GLOBALS array (although<BR>we can as the first example shows) but we alias 
them with "global". So why<BR>do this with globals and not members?<BR><BR>But 
all this is messy simply because of the fact that functions don't<BR>inherit 
from enclosing scopes. IMO, this is a flaw in the PHP language and<BR>has 
created the mess we're now in. So after all this reasoning, my proposal<BR>boils 
down to either:<BR><BR>1. Inherit identifiers from enclosing scopes as other 
languages do.<BR><BR>OR<BR><BR>2. Make things consistent by adding an aliasing 
keyword such as "member".<BR><BR>I believe I've seen performance arguments 
against inheriting identifiers but<BR>I've asked several times for details of 
this. If it's a performance issue,<BR>why? It may be that there's a way of 
solving this by structuring the symbol<BR>table differently.<BR><BR>Mike 
Scott.<BR></DIV></BODY></HTML>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic