[PHP] insteadof considered harmful

2012-04-09 Thread Szczepan Hołyszewski

I must admit with embarrassment that after months of googling and posting 
questions to various forums I still fail to understand the purpose of the 
insteadof keyword and the insteadof clause.

As I currently see it, the whole insteadof clause is completely redundant. In 
a clause like this:

Foo::tweak insteadof Bar;

the insteadof Bar part does not specify any information that is not already 
unambiguously specified by the Foo::tweak part. Foo::tweak; already 
conveys the intention of using tweak from the trait Foo instead of any other 
trait that has a member named tweak. What if we are using seven such traits? 
Do we have to list them all after insteadof? Why do we have to explicitly 
enumerate things that we DON'T want to use?

I would like to see a small code example where the insteadof clause provides  
information that is BOTH necessary to make the program unambiguous AND cannot 
be conveyed with the simple Foo::tweak; syntax. Absent such example, I 
consider insteadof harmful because it does nothing and adds a maintenance 
chore. It should be made optional and deprecated ASAP, and removed at some 
point in the future.

Szczepan Hołyszewski

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] insteadof considered harmful

2012-04-09 Thread Szczepan Hołyszewski
 See http://us.php.net/manual/en/language.oop5.traits.php and scroll down to
 conflict resolution to see simple example. It is used to resolve method
 naming conflicts when multiple traits are used to emulate multiple
 inheritance.

I have read the manual, and the examples there are precisely my examples of 
insteadof's complete redundancy. Firstly, the manual says:

To resolve naming conflicts between Traits used in the same class, the 
insteadof operator needs to be used to chose exactly one of the conflicting 
methods.

Why, why, why? Why not just name that exactly one of the conflicting methods 
using a fully trait-qualified name? That would be completely unambiguous. It's 
a simple task of choosing one from many, and such a choice can be 
unambiguously encoded by just naming the one, without having to list the 
remaining many. It is really that simple, no strings attached.

Here's the example from the manual:

trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}

trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}

class Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
}

class Aliased_Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}

I've been analyzing these 28 lines of code for months, and I cannot for the 
life of me understand why the same information couldn't be conveyed thus:

/* no changes in the traits */

class Talker {
use A, B {
B::smallTalk;
A::bigTalk;
}
}

class Aliased_Talker {
use A, B {
B::smallTalk;
A::bigTalk;
B::bigTalk as talk;
}
}

All information is there. The insteadof clauses add nothing to the 
interpreter's knowledge of the programmer's intention. They are every last one 
of all the hundred damn percent redundant.

But perhaps there IS a purpose, only the examples in the manual fail to 
demonstrate it?

Szczepan Hołyszewski

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] DOMNode children iteration (was Re: array() returns something weird)

2009-08-26 Thread Szczepan Hołyszewski
Martin Scotta wrote:

 Fatal error: Call to a member function getAttribute() on a non-object in
 testme.php on line *121*

Yes, this is _how_ the unmodified script errors out. It is not shown in the 
output I attached in my previous message because display_errors is Off in my 
php.ini, and the line that sets it to On in my script is commented out.

 I'm using a Apache/2.2.3 (Win32) PHP/5.2.6

I am not using Apache at all. The same error can be seen when I run the script 
directly through php on the command line.

 Is the script correctly? I have removed the  in the loop

I know that iterating a DOMNode's children using firstChild and nextSibling by 
reference causes trouble, thank you. The problem is that it causes trouble 
with objects unrelated to the loop itself, e.g. to variables defined _after_ 
the loop has terminated.

 and the script returns the attached file.

Do you mean it returns what is in the output file _I_ have attached, or did 
_you_ try to attach something? If that is the case, then your attachment 
didn't get through.

 It looks like a bogus bug?

I am certain it _is_ a genuine bug. For example, in PHP when you write:

$foo = array();
echo gettype($foo);

the output should not be NULL, but in my example script (unmodified, with 
iteration by reference) things like this start happening at some point.

Regards,
Szczepan Hołyszewski

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] DOMNode children iteration (was Re: array() returns something weird)

2009-08-26 Thread Szczepan Hołyszewski
 I really can't see why you'd want to use references in the posted
 loop anyway -- it's not likely to gain you any performance, and, as
 I understand it, may actually run more slowly than the
 non-reference version.

The why is irrelevant. It is perfectly legal PHP, and while it might be 
illegal usage of DOMNode, it should only break the DOMNode, and not PHP 
execution environment.

 I don't think it's possible to answer this for sure without seeing more of
 the code -- at least the complete body of the loop, plus as far as any
 further use of the variable $child (and any other variables assigned from
 it).

OK, I modified the example to show the problem _very_ directly. I commented out 
the recursion-tracing echos, and added this code in renderObject() below the 
if() that chooses between the good and evil loop, which means that the added 
code is always executed immediately after the loop:

$x=array();
$y=y;
$z=1;
var_dump($xy,$y,$z);
echo \n;

Note that these variables:

 - are first defined at this point
 - are initialized immediately
 - are initialized with immediate data (empty array and two scalars), not
   with results of prior computation
 - are never used or changed except for being dumped
 - don't get any references to them created

Therefore one must expect that var_dump will always dump this:

array(0) { 
}  
string(1) y  
int(1)

However it sometimes dumps this:

NULL   
NULL   
NULL

Best regards,
Szczepan Holyszewski
attachment: testme.php
-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP] DOMNode children iteration (was Re: array() returns something weird)

2009-08-24 Thread Szczepan Hołyszewski

Hi Lars and list!

New facts about the strange bug initially diagnosed as array() returning NULL:

Firstly, the issue is not really about array() returning null, but about full 
blown UndefinedBehavior(TM) progressively trashing local variables. It just so 
happened that I noticed it first with a variable to which array() had been 
assigned just before things began breaking.

Secondly, I proudly present the culprit: things break when I iterate over a 
DOMNode's children *by reference* using firstChild and nextSibling:

for($child=$node-firstChild; $child; $child=$child-nextSibling) {

//processing...
}

No problems if iteration is done by value or by DOMNodeList (childNodes, 
DOMXPath...).

HOWEVER,

I still consider this a bug because it destablizes PHP. After the evil loop 
has finished, things happen that should never happen, like a variable being 
NULL immediately after being assigned array().

I attach a demonstration. It is a self-contained commented script that you can 
execute from command line. Also attached is output on my machine.

Best regards,
Szczepan Hołyszewski
attachment: testme.php
THE GOOD WAY (DOMNodeList):

Recursion structure:

-render()
-render()
-render()
-
-render()
-
-
-

Transformation result:

Some text.
[object type='foo' name='bar'][param name='__default_content']
Some parameter text.
Some parameter text.
[object type='bar' name='nested'][param name='__default_content']
Some nested parameter text.
Some nested parameter text.
[object type='baz' name='deeply_nested'][param 
name='__default_content']
[/param][param name='bold']true[/param][/object]
More nested parameter text
More nested parameter text
[/param][/object]
[/param][/object]
Some more text

Success!

THE MIXED WAY (DOMNodeList at outermost level, then firstChild/nextSibling by 
ref):

Recursion structure:

-render()
-render()
-render()
-
-render()
-
-
-

Transformation result:

Some text.
[object type='foo' name='bar'][param name='__default_content']
Some parameter text.
Some parameter text.
__default_content[param 
name='__default_content']__default_content[/param][/object]
[/param][/object]
Some more text

Is it really a success?

THE EVIL WAY (firstChild/nextSibling by ref):

Recursion structure:

-render()
-render()
-render()
-
-render()
-

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP] array() returns something weird

2009-08-22 Thread Szczepan Hołyszewski
Hello!

I am almost certain I am hitting some kind of bug. All of a sudden, array() 
stops returning an empty array and starts returning something weird. The weird 
thing behaves as NULL in most circumstances (e.g. gettype() says NULL), 
except:

$foo=array();  // -- weird thing returned
$foo[]=bar;

causes Fatal error: [] operator not supported for strings, which is different 
from the regular behavior of:

$foo=null;
$foo[]=bar;  // -- $foo simply becomes an array

The problem is not limited to one place in code, and indeed before the fatal 
caused by append-assignment I get several warnings like array_diff_key(): 
Argument #1 is not an array, where the offending argument receives a result of 
array().

The effect is not random, i.e. it always breaks identically when the same 
script processes the same data. However I was so far unable to create a 
minimal test case that triggers the bug. My script is rather involved, and 
here are some things it uses:

 - Exceptions
 - DOM to-fro SimpleXML
 - lots of multi-level output buffering

Disabling Zend Optimizer doesn't help. Disabling Zend Memory Manager is 
apparently impossible. Memory usage is below 10MB out of 128MB limit.

Any similar experiences? Ideas what to check for? Workarounds?

From phpinfo():

PHP Version:
5.2.9 (can't easily upgrade - shared host)

System:
FreeBSD 7.1-RELEASE-p4 FreeBSD 7.1-RELEASE-p4 #0: Wed Apr 15 15:48:43 UTC 2009  
amd64

Configure Command:
'./configure' '--enable-bcmath' '--enable-calendar' '--enable-dbase' '--enable-
exif' '--enable-fastcgi' '--enable-force-cgi-redirect' '--enable-ftp' '--
enable-gd-native-ttf' '--enable-libxml' '--enable-magic-quotes' '--enable-
maintainer-zts' '--enable-mbstring' '--enable-pdo=shared' '--enable-safe-mode' 
'--enable-soap' '--enable-sockets' '--enable-ucd-snmp-hack' '--enable-wddx' 
'--enable-zend-multibyte' '--enable-zip' '--prefix=/usr' '--with-bz2' '--with-
curl=/opt/curlssl/' '--with-curlwrappers' '--with-freetype-dir=/usr/local' '--
with-gd' '--with-gettext' '--with-imap=/opt/php_with_imap_client/' '--with-
imap-ssl=/usr/local' '--with-jpeg-dir=/usr/local' '--with-libexpat-
dir=/usr/local' '--with-libxml-dir=/opt/xml2' '--with-libxml-dir=/opt/xml2/' 
'--with-mcrypt=/opt/libmcrypt/' '--with-mhash=/opt/mhash/' '--with-mime-magic' 
'--with-mysql=/usr/local' '--with-mysql-sock=/tmp/mysql.sock' '--with-
mysqli=/usr/local/bin/mysql_config' '--with-openssl=/usr/local' '--with-
openssl-dir=/usr/local' '--with-pdo-mysql=shared' '--with-pdo-sqlite=shared' 
'--with-pgsql=/usr/local' '--with-pic' '--with-png-dir=/usr/local' '--with-
pspell' '--with-snmp' '--with-sqlite=shared' '--with-tidy=/opt/tidy/' '--with-
ttf' '--with-xmlrpc' '--with-xpm-dir=/usr/local' '--with-xsl=/opt/xslt/' '--
with-zlib' '--with-zlib-dir=/usr'

Thanks in advance,
Szczepan Holyszewski

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] array() returns something weird

2009-08-22 Thread Szczepan Hołyszewski
 What it looks like to me is that something is causing $foo to be a
 string before the '$foo[] = bar;' line is encountered. What do you
 get if you put a gettype($foo); just before that line?

 $foo=null;
 $foo[]=bar;  // -- $foo simply becomes an array

NULL. That is the problem. I _did_ put a gettype($foo) before the actual line.

OK, here are exact four lines of my code:

$ret=array();
foreach(self::$_allowed as $r = $a)
if ($a)
$ret[]=$r;

As you can see, there is not a shred of a chance for $ret to become something 
other than empty array between initialization and the last line in the above 
snippet which causes the fatal errror. There's no __staticGet in 5.2.9, so 
self::$_allowed cannot have side effects.

Secondly, the above code starts failing after it has executed successfully 
dozens of times (and yes, the last line _does_ get executed; in fact self::
$_allowed contains configuration information that doesn't change at runtime).

Thirdly...

  The problem is not limited to one place in code, and indeed before the
  fatal caused by append-assignment I get several warnings like
  array_diff_key(): Argument #1 is not an array, where the offending
  argument receives a result of array().

 This would appear to support my suspicion, but try inserting the
 gettype($foo) (or better, var_export($foo);) just before one of the
 lines which triggers the error, and post the results.

No, I don't think it supports your suspicion. Conversely, it indicates that 
once array() returns a strangelet, it starts returning strangelets all over 
the place. Initially it only triggers warnings but eventually one of the 
returned strangelets is used in a way that triggers a fatal error.

As per your request:

//at the beginning of the script:

$GLOBALS['offending_line_execution_count']=0;

// /srv/home/[munged]/public_html/scripts/common.php line 161 and on
// instrumented as per your request:

public static function GetAllowed() {

if (debug_mode()) echo 
++$GLOBALS['offending_line_execution_count'].br/;
$ret=array();
if (debug_mode()) echo var_export($ret).br/;
foreach(self::$_allowed as $r = $a)
if ($a)
$ret[]=$r;

if (self::$_allowEmpty) $ret[]=;
return $ret;
}

Output tail:
---
28
array ( )
29
array ( )
30
array ( )
31
array ( )
32
array ( )

Warning: array_diff_key() [function.array-diff-key]: Argument #1 is not an 
array 
in /srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 350

Warning: Invalid argument supplied for foreach() in 
/srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 351

Warning: array_merge() [function.array-merge]: Argument #2 is not an array in 
/srv/home/u80959ue/public_html/v3/scripts/SimpliciText.php on line 357

Warning: Invalid argument supplied for foreach() in 
/srv/home/u80959ue/public_html/scripts/common.php on line 28

Warning: Invalid argument supplied for foreach() in 
/srv/home/u80959ue/public_html/scripts/common.php on line 28

Warning: Invalid argument supplied for foreach() in 
/srv/home/u80959ue/public_html/scripts/common.php on line 28
33
NULL

Fatal error: [] operator not supported for strings in 
/srv/home/u80959ue/public_html/scripts/common.php on line 168
--

The warnings come from other uses of array().

But wait! There is this invocation of debug_mode() between initialization of 
$ret var_export. Let's factor it out to be safe:

$debugmode=debug_mode();
if ($debugmode) echo 
++$GLOBALS['offending_line_execution_count'].br/;
$ret=array();
if ($debugmode) echo var_export($ret).br/;

And now the output ends with:


Warning: Invalid argument supplied for foreach() in 
/srv/home/u80959ue/public_html/scripts/common.php on line 28
33

Fatal error: [] operator not supported for strings in 
/srv/home/u80959ue/public_html/scripts/common.php on line 169


No NULL after 33? What the heck is going on? Does array() now return something 
that var_exports to an empty string, or does it destroy local variables? Let's 
see:

if ($debugmode) echo var_export($ret).br/; else echo 
WTF?!?!?br/;

And the output:

Warning: Invalid argument supplied for foreach() in 
/srv/home/u80959ue/public_html/scripts/common.php on line 28
33
WTF?!?!?

Fatal error: [] operator not supported for strings in 
/srv/home/u80959ue/public_html/scripts/common.php on line 169
---

Indeed, the use of array(), once it starts misbehaving, wreaks havoc in the 
local scope (possibly including the 

Re: [PHP] array() returns something weird

2009-08-22 Thread Szczepan Hołyszewski
 Hm. . .it does look odd. Searching the bugs database at
 http://bugs.php.net does turn up one other report (at
 http://bugs.php.net/bug.php?id=47870 ) of array() returning NULL in
 certain hard-to-duplicate circumstances on FreeBSD,

Yes, I found it even before posting here, but I wasn't sure whether to file a 
new report or comment under this one. If your intuition is that these bugs are 
related, then I will do the latter. Thank you for your attention.

 I don't suppose you have a development environment on another
 machine where you can test another version of PHP?

Assuming you mean a FreeBSD environment, nope :( but I will try on Linux 
tomorrow.

Regards,
Szczepan Holyszewski


-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php