For the uninitiated, there's an OO interface to the filehandles in Perl. All you do is use IO::Handle and at the expense of a mere *cough* few thousand lines of Perl code, you can replace non-OO access to filehandles:
OK, lesson over.open(my $foo,'<+ /dev/null'); #old select($foo); $|=1; select(STDOUT); print $foo "|<3wl! 31337 d00d!"; printf $foo "%.02f", $money; $fd = fileno $foo; read($foo, $input, 1024) unless eof $foo; @stats = stat $foo; close $foo; #new $foo->autoflush(1); $foo->print("|<3w1! 0bj3ct 0r13nt3d f1l3h4ndl3z! l33t!"); $foo->printf("%.02f", $money); $fd = $foo->fileno; $foo->read($input, 1024) unless $foo->eof; @stats = $foo->stat; $foo->close;
Everybody back with me? Good.
Now, some people may be familiar with this nifty oneliner, that demonstrates the nature of the magic by which Perl associates filehandles with the IO::Handle package:
This shows that Perl is magically understanding that STDIN is a filehandle being used as an object, and trying to invoke IO::Handle::close, and failing (because IO::Handle wasn't required).$ perl -le 'STDIN->close()' Can't locate object method "close" via package "IO::Handle" at -e line + 1.
I've known about this problem, but something occurred to me today that reveals a serious issue with this magic. Please read on, I'd like to know if anyone agrees with me.
-
According the normal rules of engagement, this should invoke STDIN::close() as a method. People understanding the problem in 347618 will know his right away.perl -le '{package STDIN;sub close{print "case closed"}} STDIN->close( +)'Instead, the error "can't find method 'close' in IO::Handle" occurs, indicating that Perl is actually trying to treat the bareword STDIN as a bareword filehandle first, and as a package name second.
While that may not be 100% optimal, the fact that filehandles have no identifying sigil makes this a necessary evil. So, I took it one step further.
-
Again, I get "can't find method 'close' via IO::Handle", instead of "case closed". I guessed that Perl was trying harder to do the filehandle thing than I thought.perl -le '{package STDIN;sub close{print "case closed"}} "STDIN"->clos +e()'
Still IO::Handle.perl -le '{package STDIN;sub close{print "case closed"}}my $foo="STDIN +"; $foo->close()'Perl is apparently trying to treat $foo as a symbolic reference to *STDIN, and doing the filehandle thing.
I finally get to the real kicker:
-
Lo and behold:perl -Mstrict -Wle '{package STDIN;sub close{print "case closed"}}my $ +foo="STDIN"; $foo->close()'Can't locate object method "close" via package "IO::Handle" at -e line 1.
Comments?
$"=$,,$_=q>|\p4<6 8p<M/_|<('=> .q>.<4-KI<l|2$<6%s!<qn#F<>;$, .=pack'N*',"@{[unpack'C*',$_] }"for split/</;$_=$,,y[A-Z a-z] {}cd;print lc
|
---|