[PHP] insteadof considered harmful
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
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)
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)
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)
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
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
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
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