On Wed, Jul 10, 2013 at 7:08 AM, Shawn H Corey <shawnhco...@gmail.com>wrote:

> Auto-flush is a de-optimization. Don't set it.



More "Best Practices" on autoflush (note, the original book "Perl Best
Practices" by Damian Conway is well worth the price. Even for those few you
may not agree with, practices-wise, you'll learn something:
http://shop.oreilly.com/product/9780596001735.do

)
10.18. Autoflushing

 Avoid a raw select when setting autoflushes .

 When it comes to maintainable code, it doesn't get much worse than this
commonly used Perl idiom:

select((select($fh), $=1)[0]);


 The evil one-argument form of select  [*] takes a filehandle and makes it
the (global!) default destination for print statements from that point
onwards. That is, after a select , instead of writing to *STDOUT , any print
statement that isn't given an explicit filehandle will now write to the
filehandle that was select 'd.

 [*] As opposed to the evil four-argument select (see Chapter 8).

 This change of default happens even if the newly selected filehandle was
formerly confined to a lexical scope:

for my $filename (@files) {*
#

Open

a lexical handle (will be automatically closed at end of iteration)*
open my $fh, '>', $filename or

next

;*
# Make it the default print target...*
select $fh;*
# Print to it...*
print "[This file intentionally left blank]\n"; }


 In actual applications, that last print statement would probably be
replaced by a long series of separate print statements, controlled by some
complex text-generation algorithm. Hence the desire to make the current $fh the
default output filehandle, so as to avoid having to explicitly specify the
filehandle in every print statement.

Unfortunately, because select makes its argument the global default for print
, when the final iteration of the loop is finished, the last file that was
successfully opened will remain the global print default. That filehandle
won't be garbage-collected and auto-closed like all the other filehandles
were, because the global default still refers to it. And for the remainder
of your program, every print that isn't given an explicit filehandle will
print to that final iterated filehandle, rather than to *STDOUT .

So don't use one-argument select . Ever.

And that appalling select statement shown at the start of this guideline?

select((select($fh), $=1)[0]);


 Well, that's the "classic" way to make the filehandle in $fh autoflush;
that is, to write out its buffer on every print, not just when it sees a
newline. First, you select the filehandle you want to autoflush ( select($fh)
). Then you set the punctuation variable that controls autoflushing of the
currently selected filehandle ( $=1 ). The sneaky bit is that you do those
two things in a list ( (select($fh), $=1) ), so their return values become
the two values of that list. Because select returns the previous default
filehandlethe one that you just replacedthat previous filehandle must now
be the first element of the list. So if you index back into the list,
requesting the first element ( (select($fh), $=1)[0] ), you'll get back the
previously selected filehandle. Then all you need to do is pass that
filehandle to select again ( select((select($fh), $=1)[0]) ) to restore the
original default, and your journey to the Dark Side will be complete [*] .

 [*] Once you start down that path , forever will it dominate your
maintenance...confuse you, it will!

 Fortunately, if you're using lexical filehandles, there's no need for this
kind of necroselectomancy. Lexical filehandles act like fully-fledged
objects of the IO::Handle class so, if you're willing to load the IO::Handle
module, there's a much simpler method for setting their autoflush
behaviour:


use IO::Handle;*# and later...*

$fh->autoflush( );

  You can even use this same approach on the standard package-scoped
filehandles:


use IO::Handle;*# and later...*

*STDOUT->autoflush( );


a

Andy Bach,
afb...@gmail.com
608 658-1890 cell
608 261-5738 wk

Reply via email to