Gabeezus, I have to get to work Stas! ;) > > This is the way it is, though Nikita strongly disagrees that they > > should be "callable, visible" methods on the object and I agree with > > Nikita on this issue, I never did like the idea that __getHours() and > > I think PHP engine has enough complexity and we do not need to add more > unwarranted one. These are methods, they exist - so > they should exist everywhere methods exist. Doing otherwise will result in a > tons of inconsistencies and weird occurrences. If you > are in __getHours method but the engine says __getHours does not exist and > can not be called, it is bad magic. There's no use case > for this bad magic and I see no reason for it except for us trying to > restrict users for purist reasons. I do not think the engine needs > complex bad magic when simple solution of making regular methods would work > just as well in all cases where methods work.
I very much disagree, engine details should not be visible to users. It is irrelevant to them and only serves to confuse. > > > If I were to go about this again, they probably will not be methods of > > the class. Internally there is little requiring an op_array to be > > attached to a class in order to be executed. > > So methods of what would they be? What would be their scope? What would $this > mean? What would method name and backtrace > report? How debugging/profiling tools would work with them? I see no need to > reinvent complex APIs that would require dozens of > changes in all tools dealing with PHP engine when simple methods approach > would work as well. > If they won't be regular methods I think it would be too much trouble to have > yet another entity which is "like method but not really > a method" > in the engine. To be clear, they would be regular methods, they would just not exist in the HashTable *functions of the class. In every other way they are methods of the class. > > The reason that = NULL and != NULL was chosen is because isset() and > > unset() are special states that are available only to a variable or > > property, since a get/set do not return a real property they cannot be > > used with isset/unset. Now that there has been discussion of an > > I'm not sure I understand here. Property can be either set (exists and not > storing null) or not, there's nothing special about it - all > variables and properties work this way. Automatic isset should work > *exactly* like plain PHP's isset(), and unset should make variable into the > state where isset returns false (and resources are freed). > The code in the RFC for isset() is not working like PHP's isset. That should > be fixed. > PHP 5.4.7 (cli) (built: Sep 13 2012 09:32:31) Copyright (c) 1997-2012 The PHP Group Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies with DBG v4.6.1, (C) 2000,2012, by Dmitri Dmitrienko [root@deploy /opt/esp/release]# php -ddisplay_errors=1 -ddisplay_startup_errors=1 -a Interactive shell php > function a() { return 1; } php > unset(a()); Fatal error: Can't use function return value in write context in php shell code on line 1 php > isset(a()); Fatal error: Can't use function return value in write context in php shell code on line 1 See the problem? > > This is covered in the RFC, perhaps not clearly enough (let me know > > how I could expand on it further for clarity). To answer each of > > Yes, it needs to be expanded, since no examples right now show how it is > supposed to be working. How would you like me to expand on it? > > > I, perhaps mistakenly, assumed that if return-by-ref and sort() worked > > properly, then all other "usages of references" should equally work > > the same, is that not right? If it's not right, why not? > > I'm not sure, I didn't check all of them yet. All these need to be tested. I don't know the other "contexts" that need to be tested. There are already over 80 tests written for this (.phpt) that all pass, please let me know what other tests need to be written and I'd be happy to write them. > > Certainly, this basic object oriented functionality, of course it is > > upheld. This is one of the reasons I leveraged standard functions in > > the first place, because these issues were automatically handled by > > the existing core. > > I'm not sure overriding "public $foo" with "public $foo { protected > get() {} }" is covered by existing code. Existing code has no way to cover > such things. This isn't over-riding, this is simultaneous existence and at present, properties shadow accessors, though Nikita wants to invert that. > > This is currently up in the air on the RFC side and is being referred > > to as which "shadows" which. The code currently has it that > > properties shadow accessors, Nikita suggested that should be inverted > > and I agree, so unless someone else thinks otherwise, accessors will > > probably shadow properties. > > Which raises the question above again - how LSP is preserved? What would > happen in such case? It's preserved in the same exact way (and by the same exact code) that any other function over-rides are handled. The accessor syntax, LITERALLY, translates into functions and thus go through the ordinary LSP preservation lines of code. It's the reason I chose to go that route in the first place (to leverage the existing LSP checks) > > > See response to #2 above, without a getter/setter returning a real > > property, isset/unset accessors were necessary because > > isset()/unset() cannot perform on a dynamic value. Consider this: > > You seem to misunderstand what I wrote there. I am proposing that > isset() would a) always have default implementation if get() is defined and > b) work exactly like PHP isset() in that the way that if > get() returns null (or does not exist if write-only properties are > introduced) then it returns false, otherwise it returns true. > The fact that current isset() operator does not work on T variables is > irrelevant, since I'm talking about level below that - how that > operator is implemented. The implementation should be augmented so that for > properties with accessors it would work exactly the > same as for properties without ones. With isset/unset accessors, they *can be* implemented appropriately, with automatic isset/unset implementations, they cannot, for reasons stated above: php > isset(a()); Fatal error: Can't use function return value in write context in php shell code on line 1 > > direction of accessors shadowing properties, I could see the default > > implementation of isset/unset actually be more like unset() { return > > unset($this->bar); } and isset() { return isset($this->bar); } > > If this is pseudocode, meaning "call get accessor if exists and return true > if return value is not null, otherwise return false" then it's > fine for isset. For unset, you'd still want to use set accessor or fail if > set accessor is not defined. You've got that right... isset() cannot exist (and is not allowed) if a getter is not defined, the inverse is true of unset. > > Oh crap, you're referring to the idea that during compilation a class > > definition may exist below the point of "current compilation," right? > > I had not considered this case and you're right, this would break > > badly. > > Yes, class definition is runtime, when you compiling code you have no idea > not only what this class is, but thanks to $foo::bar also > what this class' name is (which is no different since if you had the name you > still had no idea what class is under this name). Yes, these cases were not considered. The static accessors portion of this project took up an inordinate amount of time as compared to the rest. > > > of how it worked. I still do not know if I could make this work at > > the vm/opcode level during runtime but I'd be much more willing to > > give it a go now. > > I think you'd need some additional hooks in the class structure for this and > some additional methods in zend_object_handlers.c. If > you need more on this please send me a message, I'll try to help you (though > next 2 weeks I'll have very sketchy internet access as > I'm on vacation/traveling, so please be patient :) > Yes! I could really use some help in this area. I will PM you because I never knew which way to go or which way would be acceptable (adding new opcodes, messing with existing opcodes, etc). I would like to get static accessors calling into zend_object_handlers.c the way objects are but it was beyond me how to do this when I was struggling to find a way. I was actually quite excited when I found code in the core which "back patches" the op array to accomplish some things, because it gave me "the way" to make this work. Now that you've brought these valid points up, my implementation will not work. > > You and Nikita get your gloves on, makes it easier on me to go your > > direction but Nikita did not like this at all. > > Well, I think I've explained my approach above, if Nikita has something to > add he's most welcome. > > > This would refer to the fact that a debug backtrace would show that > > it's in a function called __getHours() (for example) which would only > > serve to confuse a php developer who doesn't know that a getter for > > $Hours is really a function named __getHours(). Therefore I will be > > I think it's a wrong approach to lie to the developer in order to make it > "easier". If the engine has function __getHours, it should say > so. > The developer smart enough to use properties is smart enough to understand > very simple concept of auto-generated function name > (given that __get exists for years in the engine). But what is the value of it? The developer is working within the context of an accessor, not an implementation detail which doesn't mean anything to them? > > I could not get this point across to anyone but gave up, private final > > set(); != read-only. With a non "read-only" keyword scenario, a "set" > > call would still be allowed and would show up as an access violation > > to outside observers and would be allowed from within the class. This > > is not what I wanted but I had enough other points of contention and I > > yielded on this. > > I see. I guess this should be TODO then, maybe somebody will have better > ideas. I really don't like special case keywords, so it'd be > great if we could figure it out using generic approach or maybe some light > magic like autogenerated method throwing predefined > exception. In this regard, I have yet to see any proposal that is as clear or concise as public read-only $abc. What is the big problem with adding read-only and write-only keywords? Once they are in the language they could be expanded to plain properties. > -- > Stanislav Malyshev, Software Architect > SugarCRM: http://www.sugarcrm.com/ > (408)454-6900 ext. 227