Hi all,
I just published an RFC that proposes to add catch-statement without needing to specify a variable, and support for fully anonymous catches.
Details can be found at:
https://wiki.php.net/rfc/anonymous_catch
Regards,
Joost Koehoorn
Joost,
First off, let me say welcome and thanks for the contribution!
I have a couple of questions around the intended proposal.
-
How do you plan on handling the case where there are multiple catch
blocks?try {
code();
} catch {
doSomething();
} catch {
doSomethingElse();
} -
You mention as a benefit "Better possibilities for static analysis
tools". Can you elaborate on this? I don't see how this sort of a change
would have any effect (as catch would be the same as the existingcatch (\Exception $e)
)... -
What benefit short of not having to type
(\Exception $e)
would this
have? Populating the symbol table is extremely cheap at this stage, because
the variable is already compiled in (so no hash table lookup or anything).
Additionally, I would recommend changing the version target to 5.NEXT
(which would be 5.6 in practice).
As far as my personal feelings, I'd like to get some other commentary first.
Thanks again!!!
Anthony
Joost,
First off, let me say welcome and thanks for the contribution!
I have a couple of questions around the intended proposal.
- How do you plan on handling the case where there are multiple catch blocks?
try {
code();
} catch {
doSomething();
} catch {
doSomethingElse();
}
As mentioned as latest sentence in the Proposal chapter, an anonymous catch can only be used as the latest catch, and there can only be one of them. This is also how my current implementation works.
-
You mention as a benefit "Better possibilities for static analysis tools". Can you elaborate on this? I don't see how this sort of a change would have any effect (as catch would be the same as the existing
catch (\Exception $e)
)...
It's mostly for finding unused variables. I suppose that static analysers currently ignore unused exception variables, but they don't have to when this is accepted and can properly indicate unused exception variables. -
What benefit short of not having to type
(\Exception $e)
would this have? Populating the symbol table is extremely cheap at this stage, because the variable is already compiled in (so no hash table lookup or anything).
Performance wise it's indeed very minor and doesn't really matter. It's more that you're adding code indicating that only a specific exception is used, while that may not really be the case.
Consider Java people --Java has Throwable as the superclass of Exception-- they may not know that in PHP 'Exception' is the least-specific type and therefore used as catch-all.
As for leaving of the variable, the type of an exception mostly tells enough about what happened (well, it should), so you don't have to inspect the exception's error code/message and thus don't need the exception object at all.
Additionally, I would recommend changing the version target to 5.NEXT (which would be 5.6 in practice).
Done!
As far as my personal feelings, I'd like to get some other commentary first.
Thanks again!!!
Anthony
On Mon, Jun 24, 2013 at 7:49 PM, Joost Koehoorn joost.koehoorn@gmail.comwrote:
Joost,
First off, let me say welcome and thanks for the contribution!
I have a couple of questions around the intended proposal.
How do you plan on handling the case where there are multiple catch
blocks?try {
code();
} catch {
doSomething();
} catch {
doSomethingElse();
}
As mentioned as latest sentence in the Proposal chapter, an anonymous
catch can only be used as the latest catch, and there can only be one of
them. This is also how my current implementation works.You mention as a benefit "Better possibilities for static analysis
tools". Can you elaborate on this? I don't see how this sort of a change
would have any effect (as catch would be the same as the existingcatch (\Exception $e)
)...
It's mostly for finding unused variables. I suppose that static analysers
currently ignore unused exception variables, but they don't have to when
this is accepted and can properly indicate unused exception variables.What benefit short of not having to type
(\Exception $e)
would this
have? Populating the symbol table is extremely cheap at this stage, because
the variable is already compiled in (so no hash table lookup or anything).
Performance wise it's indeed very minor and doesn't really matter. It's
more that you're adding code indicating that only a specific exception is
used, while that may not really be the case.Consider Java people --Java has Throwable as the superclass of Exception--
they may not know that in PHP 'Exception' is the least-specific type and
therefore used as catch-all.As for leaving of the variable, the type of an exception mostly tells
enough about what happened (well, it should), so you don't have to inspect
the exception's error code/message and thus don't need the exception object
at all.Additionally, I would recommend changing the version target to 5.NEXT
(which would be 5.6 in practice).
Done!As far as my personal feelings, I'd like to get some other commentary
first.Thanks again!!!
Anthony
--
I'm just going to weigh-in here with my two cents.
When I look at the facts objectively I don't see a reason to turn down this
proposal, but I also don't see much of a reason to accept it. My only fear
is that people will abuse anonymous catch blocks in situations where it
would have been better to just properly handle the Exception.
For example, if you're doing this in your code you're probably writing some
pretty bad code that's tough to debug...
try
{
$this->connectToServer();
} catch {
$this->retry(3);
}
Why are we throwing Exceptions if we only want to retry the connection in
the event that it failed? That would be more likely better handled by the
callee where the connection can be retired up to a timeout or number of
re-attempts until it fails permanently and then throws an Exception.
Exceptions should be like broken promises. If the promise the method or
function makes can't be kept it should throw an Exception to notify the
caller and the caller should decide how to proceed from there. If the
caller doesn't care that the promise could not be kept they probably have
very special circumstances to consider. So I can live with catch(Exception
$e) { /* ignore $e */ }, but that's my only objection. It's one purely from
a stand-point of promoting better code.
I understand a lot of other languages may allow this, but then again a lot
of other languages give you more room to shoot yourself in the foot than
PHP does.
I'm pretty neutral about this feature overall.
On Tue, Jun 25, 2013 at 12:54 AM, Joost Koehoorn
joost.koehoorn@gmail.com wrote:
Hi all,
I just published an RFC that proposes to add catch-statement without needing to specify a variable, and support for fully anonymous catches.
Details can be found at:
https://wiki.php.net/rfc/anonymous_catch
Regards,
Joost Koehoorn
--
Hi,
First of, considering that you would only save three characters by
having the ' $e' removed, I don't see how it would make things easier
to learn. I mean if you can't learn that maybe you should look into
something else that's not related to programming :)
Having this: "* Avoid indication of a specific exception type" could
be considered as a possible bad practice, just as you were saying that
catch(\Exception $e) is. Also, it you can add the other ten characters
that you save when typing \Exception but does it worth it?
How do you plan to handle this: * Note that there may only be one
anonymous catch-statement, and it has to be the last one. Throw a
fatal error? If not then what, nothing?
What are the performance downsides of having this check in place? I do
understand that you mentioned: "* Runtime needs to perform less
checks. No need to update the symboltable, no need to check exception
inheritance. " but wouldn't that be replaced by what I'm asking about?
If I could read/understand C better I wouldn't ask for this.
Could you also please elaborate this: "* Better possibilities for
static analysis tools"?
As for: * People from other languages such as C#, Python and Ruby
expect this to work I think it is often pointed out when requesting
features such as function/method return type hinting (I'm planning a
RFC for that), named parameters, threads and other stuff that this
ain't C#, Java, Python, Ruby or whatnot so.. what's the official
position on this? Do we want PHP like the other languages or not (and
I won't say more on this here/now)?
Also, the code sample is not that good. If you want to reflect a good
quality scenario, it should be more like:
while (true) {
try
{
$this->connectToServer();
break;
}
catch (ConnectionFailedException)
{
sleep(3);
}
}
And I think the RFC should also add a: Disadvantages section so that
it could help people looking on it and proving that you've done all
the research correctly.
Thanks
Florin Patan
https://github.com/dlsniper
http://www.linkedin.com/in/florinpatan
On Tue, Jun 25, 2013 at 12:54 AM, Joost Koehoorn
joost.koehoorn@gmail.comwrote:
Hi all,
I just published an RFC that proposes to add catch-statement without
needing to specify a variable, and support for fully anonymous catches.Details can be found at:
No opinion on leaving off $e, but I'm against the generic catch{} statement.
Looking at the Python docs, they don't see particularly fond of the
wildcard-except themselves:
The last except clause may omit the exception name(s), to serve as a
wildcard. Use this with extreme caution, since it is easy to mask a real
programming error in this way! It can also be used to print an error
message and then re-raise the exception (allowing a caller to handle the
exception as well):
Furthermore a wildcard-catch is bad for forwards compatibility. Right now
all exceptions extend Exception, but this doesn't have to stay so. E.g.
Python has additional exceptions above that for handling stuff like signal
interrupts or die()s and I think it's not unlikely that we will introduce
something like this in PHP too. You normally do not want to catch those,
but a wildcard-catch would do this.
Thus I think it's better to stays explicit and keep it at catch(Exception).
Nikita
No opinion on leaving off $e, but I'm against the generic catch{} statement.
I second the concerns about empty catch{}.
--
Regards,
Mike
On 25 June 2013 17:07, Nikita Popov nikita.ppv@gmail.com wrote:
No opinion on leaving off $e, but I'm against the generic catch{} statement.
I second the concerns about empty catch{}.
--
Regards,
Mike
As most of you seem to discard the idea about and empty catch (I can see why, no problems), maybe it's best to focus on only leaving of the variable then, that's something most of you seem to agree with, until now.
2013/6/25 Nikita Popov nikita.ppv@gmail.com:
but I'm against the generic catch{} statement.
I'm sharing Nikita's opinion, with the difference of a bit more
enthusiasm on leaving off the variable as it could make it more
obvious that there is no intention in using the variable, and that no
memory should be kept for it. This might be better than doing:
try {
[...]
} catch (Exception $ignore) {
unset($ignore);
}
[...]
However, I see other cases where a variable is technically required
but not used:
abstract class AbstractPrinter {
abstract public function print($message);
}
class Printer extends AbstractPrinter {
public function print($message) {
echo $message;
}
}
class BlackholePrinter extends AbstractPrinter {
public function print($message) {
}
}
In the previous example, $message is not "used" in
BlackholePrinter::print() (as well as in AbstractPrinter::print()).
How do you intend to make that consistent with: catch(Exception) ?
Patrick
2013/6/25 Nikita Popov nikita.ppv@gmail.com:
but I'm against the generic catch{} statement.
I'm sharing Nikita's opinion, with the difference of a bit more
enthusiasm on leaving off the variable as it could make it more
obvious that there is no intention in using the variable, and that no
memory should be kept for it. This might be better than doing:
try {
[...]
} catch (Exception $ignore) {
unset($ignore);
}
[...]
However, I see other cases where a variable is technically required
but not used:
abstract class AbstractPrinter {
abstract public function print($message);
}
class Printer extends AbstractPrinter {
public function print($message) {
echo $message;
}
}
class BlackholePrinter extends AbstractPrinter {
public function print($message) {
}
}
In the previous example, $message is not "used" in
BlackholePrinter::print() (as well as in AbstractPrinter::print()).
How do you intend to make that consistent with: catch(Exception) ?
Patrick
Your inheritance example is something that I do not have a good solution for (I don't think there is one) but with Exceptions it's different, because there the solution is obvious, unambiguous and expected.
That it also happens to be easy to implement is good to know, it means that the effects of this change are totally obvious (because only ONE opcode has to be changed, so there is only an effect on this ONE opcode, other code is not affected in any way, that's good to know).