On Tue, 04 Sep 2012 01:27:12 +0200, Stas Malyshev <smalys...@sugarcrm.com> wrote:

to be gained vs. the additional risk. And there is little to no benefit
in a model where rewinding a closed iterator is allowed, so the
threshold for acceptable risk is very low. This is not a difficult case
at all, IMHO.

We are discussing whether it should lead to the fatal error. I see no
reason for that and declaring "it's not difficult" does not make a
reason a bit clearer. There should be a reason for generating fatal
error, and "this may be a bug" is not a reason enough, at least not in
PHP, as long established practice in PHP clearly shows.

Yes, we are. I am saying that "reason" is a balancing of factors: (1) whether the non-exception error behavior makes sense and (2) the extent it has legitimate uses on one hand and, on the other hand (3) the risk it introduces.

Of course different languages balance these factors differently and PHP puts less emphasis on (3) -- I'm not trying to change that.

There is no strict technical reason  for most fatals in PHP too. Except
maybe parser errors, you usually can abstain from doing whatever action
would cause the fatal instead of raising the fatal. Calling function
that does not exist or abstract method? Return NULL (like an invalid
call btw).

Returning null is a legitimate function return, and there's no value
that can not be legitimately returned from an existing function.
Moreover, since unlike empty iterator, not calling a function is not
normal (iterators can be legitimately empty, but function can not be
legitimately non-existing) fatal error is a proper response to it. Of
course, if we used exceptions, there could be an exception thrown
instead, which is the same thing more or less.

Your distinctions here make no sense to me. I cannot understand how the first sentence is even an argument, but in any case you can also say, "Returning an empty set is a legitimate iterator return, and there's no set that cannot be legitimately returned from an existing iterator". There's also no meaningful distinction after. It boils down to what you consider "normal" and "legitimate", and for some reason you equate not traversing an iterator and replacing it with an empty one as "normal" and "legitimate", but not executing a function and replacing it with a null returning one abnormal and illegitimate.

But I'm glad you think this way. It means that you accept that the criterion for raising a fatal is not simply "will we segfault if we do this?" or "can we continue parsing if we do this?", but it is instead more nuanced, requiring us to evaluate the "normality" and "legitimacy" of non-fatal behavior, as you put it.


IMO, this is perhaps your strongest argument. But 1) that was a bad
idea, 2) we're not really talking about the behavior of foreach(), we're
talking about the behavior of specific methods that may or may not be
called in the context of a foreach, in a hierarchy where exception
throwing is well established. So it's not really analogous.

Sorry, but again I have a feeling that you are not satisfied in general
with how PHP handles errors and want much more strictness there. Which
is completely fine, but I must again emphasize that doing it by sneaking
exceptions here and there into the core is not the right way to do it.
If you want to change how PHP behaves, it should be done as a
language-level principle change, and not being done by altering bits of
random patches to behave how the "strict" people like and inconsistently
with how the rest of PHP behaves. I would be happy to discuss it, I have
a lot of issues with current error handling too, but we can not just
ignore the established principles.

I think you're misrepresenting my position. I want strictness only in the cases where the alternative behavior fails the balancing test I mention above, a test you (at least to some extent) also support. In the other e-mail you say:

So it basically comes to "it doesn't follow but E_NOTICE in fact should
be fatal for those who prefer a stricter model because I had some code
where it indicated a bug". That's exactly what I was talking about.
[...]
If however we want to keep the current nature of PHP, introducing fatal
errors where it can be avoided only because it _may be_ a bug makes
little sense - we have tons of situations where it may be a bug - just
as you described with E_NOTICE and no fatal error there.

My test is not whether it *may* be a bug, as I explained. Yes, E_NOTICEs *may* indicate a bug. But many times they will not (esp. on templates).

Now, we may disagree on this, but I content that the situation we're discussing is *almost certainly* a bug.


If we have a behavior that can be used in two contexts and it is not
consistent with one of them, it is not good to point out it may be
consistent with another. Not throwing exception in this case is
consistent with all other PHP - nothing requires that generator or
iterator would throw exceptions on every problem. In fact, I do not
believe any of the existing iterators throw on trying to iterate past
the end. So not throwing will be consistent with everything.

Nor are they supposed to to throw an exception in that case. Even though we don't document in the manual, iterators return null when they have no more elements. But let's look at rewind:

Rewinds back to the first element of the Iterator.

Making a no-op is a violation of the post-conditions rewind() is supposed to offer. And yes, I know about NoRewindIterator, which is an aberration -- classical circle is-an ellipse bad design.

In fact, I would have preferred that rewind() was not a part of Iterator, but it's too late for that.

However, throwing will be inconsistent with foreach() usage pattern and
only marginally consistent with other iterators - while they indeed
throw exceptions, as far as I can see they don't do it in normal
iteration scenarios, only when trying to pull something weird like
accessing keys of invalid iterator or when using underlying
functionality that fails. But as far as I can see you can not make any
of existing SPL iterators to throw by repeatedly iterating over them.
Even NoRewindIterator - which states "no rewind" in its name - does not
throw when you try to repeatedly iterate over it.

I disagree that this is a normal iteration scenario. And AFAIK all SPL iterators are rewindable, so it's normal we can't find examples on point.

--
Gustavo Lopes

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to