5 ms·
PHP doesn't need 'finally'
- hackermom 16y agoSyntactic sugar would be the right term for this, I guess. I think everyone who has dealt in languages not having Try-Finally can recall a case or two where it would've felt smooth and tidy to have access to Finally - but never, ever a case where they absolutely required it. No one is having problems in C/++ because of this. No one is having problems in PHP, either. And saying this will probably get me the flood of down votes, but this has always struck me as being something that is a language "requirement" only in people who have an itch in a hard-to-reach place in the engineering department of their brain - no offense meant. They need it for their sense of order, not for their software.
- Nitramp 16y agoFinally makes it much more easy, and much more readable, to do the right thing. Not having finally means duplicated code and harder to follow methods where resources have to be managed, and for most developers, this simply means resources are not managed properly at all. C++ doesn't need finally because it has deterministic destructors, which are used to emulate finally clauses. In my opinion, destructors can cause less readable/predictable code than a proper finally block, but that might be matter of taste. Comment from the language maintainer: The only difference is the second example does rethrow the exception. Though this is still possible (however much more to type) it is wrong design. Since obviously you are using the exceptions as control flow. This seems quite strange. Finally is a construct to manage control flow, and it's essential to control flow during error conditions. He seems to prefer just swallowing a (potentially critical) exception. Either I'm misreading him, or I think he fails to understand the point of either finally, or exception handling in general.
- kree10 16y ago"Finally makes it much more easy, and much more readable, to do the right thing." I think this gets to the heart of what feels 'off' about PHP to me: this kind of passive-aggressiveness against "doing the right thing" seems built-in. Kind of like how in order to avoid XSS, PHP offers htmlspecialchars(), or to avoid SQL injection, mysql_real_escape_string() (I'm aware of PDO, but it seems few if any major projects use it).
- wvenable 16y ago> C++ doesn't need finally because it has deterministic destructors PHP has deterministic destructors as well. Using them is how I get around the lack of finally -- destructors do the clean up.
- TimJYoung 16y agoQuestion: when are PHP's object destructors called ? I can see some issues with external resources if an object instance hangs around until it is garbage collected. PHP might not have an issue with this if it does GC for every page load, but other languages like the .NET languages can experience serious issues if you don't release external resources using a finally block, and rather rely on the destruction of the object to release them. In such a case, the destruction may take place a long time after the initial acquisition of the external resources. My point is that object lifetime <> external resource usage duration in all cases.
- wvenable 16y ago> when are PHP's object destructors called ? As soon as there are no more references to it. PHP is reference counted (with cycle detection). As soon as the variable containing an object goes out of scope, the destructor will be called. The fact that Java/C# destructors aren't called immediately (and may not be called at all) is the primary reason that Java has the finally block (C++ doesn't) and why C# also has the using statement.
- TimJYoung 16y agoThanks for the response. I knew that PHP was reference counted, but what I was asking (not particularly well) was more along the lines of: is it possible to have objects live longer than the scope of a single script ? IOW, is there a point at which the PHP runtime decides that it is going to collect/reclaim everything, similar to a process termination in the OS ? Or is it literally possible to implicitly allocate objects in a global fashion and have them stick around until the PHP runtime itself is terminated ? Thanks again.
- randombit 16y ago> No one is having problems in C/++ because of this. No one is having problems with this in C because C doesn't have exceptions. No one is having problems with this in C++ because C++ supports RAII via destructors which are guaranteed to run on stack unwind.
- wvenable 16y agoYou can do RAII in PHP via destructors as well. That's how I "get around" this problem.
- jaekwon 16y ago... it is wrong design. Since obviously you are using the exceptions as control flow. What convoluted understanding of "control flow" makes an exception unworthy of use as control flow? Exceptions aren't bugs, they're simply exceptional conditions. If you use them right they pose no problem but serve to make the code more legible.
- blahpro 16y agoI find it laughable that they’re arguing this from the "don’t abuse exceptions as control flow" angle considering that PHP 5.3 introduced goto.
- LiteOn 16y agoSo? Exceptions are still not supposed to be used like that.
- dan_netwalker 16y agoOh, great, another way for the rails nazies here at work to make fun of php... -_-U
- jaekwon 16y agoPHP is like legos or loxblox, mmmkay? And I'm not saying legos aren't awesome, or that you can't build a house out of it. Absolutely you can.
- dan_netwalker 16y agoYeah, I know. But working on a wood statue with a humble knife should not be an excuse for the chainsaw guy to call you a dumb bastard for not be doing the statue with the chainsaw, "like proper men should do". Yes, the quoted phrase was actually heard on my office. Go figure... ( ...and I don't have anything against ruby. I'm learning rails. www.railsforzombies.com is great. In fact, my php is made on cakephp and lithium, which are pretty similar to rails... )
- 16y ago
- joelmichael 16y agoThis looks like a PHP version of the Ruby "ensure". http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/syntax.html#begin http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/synt...
- jrockway 16y agoCan't you just implement finally in "userspace"? In Perl, you can implement it with object destruction -- you make an instance of an object whose destructor does the cleanup you want, and when it goes out of scope (exception thrown, return, etc.), the cleanup code is run. It's extremely common to write code like: sub work_in_tmpdir(&) { my $cwd = cwd; my $guard = guard { chdir $cwd }; chdir mktmp; $_[0]->(); } Then you can safely work in a temporary directory: print cwd; # /home/jon work_in_tmpdir { print cwd; die "OH NOES" }; # /tmp/3sdjkh387dh print cwd; # /home/jon If this doesn't look enough like Java, that's easy to fix: sub try(&;@) { my ($code, %args) = @_; my $guard; $guard = guard { $args{finally}->() } if exists $args{finally}; my $result = eval { $code->() }; if($args{catch} && !$result){ $args{catch}->($@); } return $result; } catch(&;@) { return catch => @_; } finally(&) { return finally => $_[0]; } (+) Now you can say: try { something_exceptional } catch { warn "Something bad happened: $_[0] } finally { cleanup }; No language feature or bug tracker rant-fest required! And, I'm pretty sure that you can abuse destructors in PHP to get exactly the same result. (In Perl, that "guard" function from the Guard module is implemented something like: class Foo { has 'cleanup' => (is => 'ro', isa => CodeRef ); sub DESTROY { $self->cleanup->() } }; sub guard(&){ return Foo->new( cleanup => $_[0] ) }) (+) Also, don't cut-n-paste this code into your apps. It misses special cases. use Try::Tiny, TryCatch, etc. from the CPAN.
- bad_user 16y agoThat's a neat example, but you're abusing Perl's syntax for that syntactic-sugar, and it doesn't work like that in PHP (e.g. parens cannot be omitted, and does this code even compile with "use strict"?)
- jrockway 16y agoIt compiles with "use strict", and it's not abuse. The reason you can't compile it is because guard is not defined, nor are cwd, cleanup, and the other placeholder functions I used. When you are relying on the parser to add parens for you (and let you omit "sub"), you have to have the function in scope. Compare: use strict; sub foo { bar } And use strict; sub bar; sub foo { bar };
- dan_netwalker 16y agoOk, wait. Time out. What whould be the difference between: try{ some ifs ... return x ... more ifs ... throw ... return y }catch{ handle exceptions }finally{ do_something_finally() } and try{ some ifs ... return x ... more ifs ... throw ... return y }catch{ handle exceptions } do_something_finally() I'm missing something, I'm not?
- gfodor 16y agoNo, you're right. The code in the above example behaves differently than the finally version in the case where UNLOCK TABLE throws something. This seems to be an example where the hack is preferred over the correct solution. The hack in this case is going to work almost all of the time. I fail to see how throwing up an example of a hack is a good way to argue for or against a language feature. Generally speaking if the language is decent enough there is always a way to hack in some new semantics yourself (I'm looking at you, anonymous inner Java classes for closures), but language features allow you to compose and represent those semantics more elegantly. So, the argument shouldn't be "can we do this already with a hack" it should be "is this hack common enough that we should fix it." The point the author is making is almost self-evidentally against his own conclusion: here's a common pattern that is broken, so we should not include this as a language feature???
- bnoordhuis 16y agoWithout the finally block, do_something_finally() will not be called if: 1. the try block returns 2. the catch block doesn't handle /all/ types of exceptions The point of finally is that it's always, always, always executed.
- BrandonM 16y ago> The point of finally is that it's always, always, always executed. Except when it's not. If you design a large system with the assumption that finally blocks always execute, you could end up with some data integrity issues when you get a power outage, an exception in your finally clause, a hung machine, or any other number of errors that a finally clause does nothing to address. The finally clause is very useful, but to say that it will always (x3!) execute is somewhat perilous.
- crad 16y agoSo if I read that right, you don't need finally because you can unlock mysql tables when catching the exception? That's brilliant. Clearly as far as the PHP team is concerned, there is no other use for PHP than using it with MySQL.
- shub 16y agoThe person who submitted the bug included an example of finally with MySQL, and the PHP guy was holding to that theme so that his response would be as clear as possible. So really, you should be blaming some random guy on the Internet for having no other use for PHP than using it with MySQL, which is more than likely true.
- morgo 16y agoWhat irritates me about this thread is the sense of entitlement from people who file bugs. If helly wants to say "there was a discussion about this on the internals list, and the decision was no" he doesn't have to justify anything more. If they still care enough, they can dig up the internals thread and re-spark discussion.
- jwatzman 16y agoOne of the notes on the report is someone who did try to dig up the discussion and couldn't find it, only a bunch of people saying without reasons "we do not need finally". It seems polite to me for someone who knows when/where said discussion was to link to it.
- rodp 16y agoA programming language is a tool and its syntax is its UI. PHP community doesn't get this. They never have. Just because you can empirically prove that a language doesn't need a feature, it doesn't mean you shouldn't add it if it's obvious that most developers would _enjoy_ using it.
- morgo 16y agoThe example is the wrong case. Unless you are using MyISAM tables (hint: 90%+ of the time you shouldn't), there's rarely a situation to LOCK TABLES as described. Using transactions would make more sense: try { mysql_query("START TRANSACTION"); // ... do lots of queries here mysql_query("COMMIT"); } catch(Exception $e) { mysql_query("ROLLBACK"); }
- dlsspy 16y agoYou left out the code where you acquire the database connection and need to release it before returning as well as propagate the success or failure of the operation.
- wvenable 16y agoJust like with C++ (which also doesn't have finally) you can use RAII techniques with PHP. Object destructors will get called when your object goes out of scope. I use this to clean up resources (mainly rollback transations) in the case of exceptions. In fact, now with PHP 5.3 and closures one could emulate finally quite easily: just create an object that runs the closure on destruction and it will be called at the end of the block. Finally would still, however, be a welcome addition to the language.
- deleted 16y ago[deleted]
- DjDarkman 16y agoI don't think 'finally' is mandatory, I have never missed it, sure it may be syntactic sugar 1% of the time, but are we developing for the rare cases now?