A localizable interface to `select`
Have you ever forgotten to restore your original STDOUT (or other handle) when you want to select
another one for a brief time? Does the usage
my $stdin = select *STDERR;
print "To STDERR";
select $stdin;
seem clunky?
I have always loved the interface provided by File::chdir. It gives you the $CWD
variable. When you assign to it you change the working directory. Even better, if you do that with the local
directive, you dynamically scope the change!
It struck me, while I was working on the test suite for another project, that I wished that I could have that same kind of interface to select
. And why not, they both need changing and restoring of a global property? So I gave it a try, and lo and behold it was simple!
So here it goes, I present Tie::Select, which provides the $SELECT
variable. Use it like this and I think you will wonder why you ever did it the other way!
use Tie::Select;
{
local $SELECT = *STDERR;
print "This goes to STDERR";
}
print "This goes to STDOUT";
I see the use of this module, but I find Tie::Select an awful name. The tie is an implementation detail, you shouldn’t expose that to your user. How about Handle::Select or something like that?
Blast, Leon you are absolutely right! While I was writing this Tie::Select seemed like the obvious name; why didn’t I see the asynchronicity between Tie::Select and File::chdir?
Ok I really like Handle::Select, but I don’t see a top-level namespace Handle. Should I go ahead anyway? Also is there a cute way to change a module’s name or do I simply upload the new one and make a Tie::Select 0.02 which is a POD-only stub?
On second thought, I’m going to leave it as Tie::Select for now. I have been trying to think of a good (existent) top-level namespace to add this to, but I can’t come up with it. Handle:: and Dynamic:: don’t exist; Local:: doesn’t either and implies timezones or languages.
Yes having it in Tie:: would seem to imply that it is a class to tie into, but I think it also gives an account of its functionality. Those Perlers who might be sufficiently advanced to want to have locally bound bound
select
call will understand how a tie works and why that interface might benefit them.Of course I would love to hear opinions.
I prefer Local::Select. There’s not confusion with timezones and/or language because that is “Locale”, with a trailing “e”.
We’ve tried to reserve Local::* as a namespace that shouldn’t ever show up on CPAN so people can use it privately without conflicts.
I’d push for something in IO::Handle::*.
Thanks for the warning brian!
I thought about going under the IO::Handle:: namespace. I ended up passing on that, since for many people this will imply an object interface, because of the IO::Handle implications.
I think that unless I were to go for Handle::Select, for parallelism with File::chdir, I will just leave it as is, for the reason I end on in my previous comment:
Those Perlers who might be sufficiently advanced to want to have locally scoped
select
call will understand how a tie works and why that interface might benefit them. The abstract will have to get them there rather than the name.I admit it may be just preference, but I find Guard objects better (as in, it’s a generic way to automatically restore state) suited for such things:
I hadn’t known about
Scope::Guard
, thanks for informing me. That definitely has its place, it can do arbitrary cleanup, and you establish the cleanup near the original mess making.Perhaps I am just too fond of tie-ing things, I think I will stick with
Tie::Select
, personally, at least for this job.You don’t need Scope::Guard, lestrrat. SelectSaver has been in core forever.
FileHandle::Select
Yikes,
SelectSaver
gets very close to coveringTie::Select
’s raison-d’etre and IMO completely coversLexical::select
.Since the dyamically scoped
$SELECT
variable provided by my module is a global property, lexical and dynamic are essentially the same.I really had never heard of that one. Ok I can take my own medicine; should I remove Tie::Select?
Heh. Sorry! I didn’t mean to obsolete your module. But yeah, knowing about both SelectSaver and Tie::Select, I don’t know what reason would compel me to use the latter. :-( Their semantics are identical, their surface syntaxes differ only superficially, but Tie::Select is an external dependency and its API consists of a global; I can’t think of a situation in which I’d pick it over SelectSaver.
I content there is a slight difference. All of the object methods rely on the DESTROY method to clean up, while
Tie::Select
has the localizing tie magic to do it for you. I know this isn’t much of a distinction, but a possible issue might be, for example https://gist.github.com/1717776 , though its admittedly a bit of a reach.Also its not a true global, its an exported package variable.