What's the best way, in your estimation, to explain to novice Perl programmers that, given the vagaries and heuristics of S_intuit_method in toke.c, it's often easier to reason about the local and global effects of any individual unit of code if there are no barewords?
Sure, but there are even more important places where this issue arises. See below.
(I can count on my fingers the number of people who may be able to explain all eight rules for S_intuit_method without having to consult the code as a refresher, and I might be overestimating the number of people so qualified. If anyone, you're one of them, but I don't count on having all novices as experienced or ready to understand in full as you.)
Here, take a shot at it yourself. ☻ Your goal is to uncomment just one from each set of sorted alternatives to produce this exact output:
Here’s the code:fileno is 2 fileno is 2 That's all, folks!
Good luck. :)sub new { die "$0: main::new() sub called\n"; } sub Class { die "$0: main::Class() sub called\n"; } ### PICK EXACTLY ONE OF: #1# local *new ; #2# local *new = Class new ; #3# local *new = Class->new() ; #4# local *new = Class::->new() ; #5# local *new = new Class ; #6# local *new = new Class:: ; ### PICK EXACTLY ONE OF: #1# open( new, "> &=STDERR") || die; #2# open( new, "> &STDERR") || die; #3# open( new, ">& STDERR") || die; #4# open( new, ">&", *STDERR) || die; #5# open( new, ">&=STDERR") || die; #6# open(*new, ">&=STDERR") || die; #7# open(*new, ">&", *STDERR) || die; my $fd = fileno(*new) // die "no fileno"; die "wrong fileno" unless $fd == 2; my $output = "fileno is $fd\n"; syswrite(*main::STDOUT, $output, length($output)); ### PICK EXACTLY ONE OF: #1# (print new $output ) || die; #2# (print "new" $output ) || die; #3# (print *new $output ) || die; #4# (print ::new $output ) || die; #5# (print {*new} $output ) || die; ### PICK EXACTLY ONE OF: #1# close( new ) ? done() : die "can't close new: $!"; #2# close( new::) ? done() : die "can't close new: $!"; #3# close( "new" ) ? done() : die "can't close new: $!"; #4# close( *new ) ? done() : die "can't close new: $!"; #5# close( ::new ) ? done() : die "can't close new: $!"; #6# close(*::new ) ? done() : die "can't close new: $!"; sub done { print "That's all, folks!\n"; } package Class; sub new { require "IO/Handle.pm"; return IO::Handle::->new(); }
This isn't about political correctness. It's about reducing the possibility of error in the same way that explaining that always, always, always adding a space between the file open mode and the filename in the two-argument form is as much a pattern for people to emulate as using the three-argument form.Yes, ok: that’s sound advice. One problem is people are unclear on what a mode even is. See all the flailing above.
You know as well as anyone that novices tend to emulate examples without understanding them fully.There are something like 650 uses of vintage filehandles in the standard documentation set, and perhaps 400 such uses in the Camel. What do you propose to do, change all those to meet the new purity laws? We already had handle autovivification in 5.6.1, and didn’t see fit to do so then. Has something changed since then? Or was that a terrible blunder? And what should be done in future? You perceive this weighs on my mind.
And what do you do when a user comes to you unhappy that the old standard copy pattern:
Has no corresponding clean translation? How do you explain that one to them? There is no nice story here: lexical filehandles can too easily break several standard practices that people have come to rely on more than they realize. It is never a pleasant task to explain these strange failures that can result.print OUTPUT while <INPUT>;
And even if the thousand or so uses of vintage filehandles were expunged from the online docs and the Camel (which I personally find to be a terrifically intimidating amount of work — which I do not care to sign myself up to!), what then do you do about the millions of uses of them in existing code that are already out there? Ban them? The current doc policy seems to be to remove all mention of things “we don’t like”; how does that serve the public good?
Encouraging them to prefer constructs where, for example, the lack of an invisible character has no potential security flaws, seems to me to be more useful.Security flaws? Don’t you think that’s unnecessarily overstating things? That’s like saying that the old rename script has security flaws:
The point here is that if you are allowing untrusted antagonists to specify the arguments to your syscalls, then you have bigger problems than mode bits.$op = shift() || die; for (@ARGV) { $was = $_; eval $op; die if $@; rename($was, $_) || die "rename: $!" unless $was eq $_; }
That said, I was aghast to find this embarrassing silliness still in perlfunc:
If you want to select on many filehandles, you may wish to write a subroutine like this:I of course fixed it to read what it should have read since oh, probably perl4 or so:sub fhbits { my(@fhlist) = split(' ',$_[0]); my($bits); for (@fhlist) { vec($bits,fileno($_),1) = 1; } $bits; } $rin = fhbits('STDIN TTY SOCK');
Filehandles seem to me to be the least of several worrisome bareword issues. In front of that concern come not just bareword strings but most especially an agonizing confusion as to what is and what is not a subroutine call, a method invocation, or even a class name. Doesn’t that bother you?sub fhbits { my @fhlist = split(" ", $_[0]); my $bits ; for (@fhlist) { vec($bits, fileno($_), 1) = 1; } return $bits; } $rin = fhbits(*STDIN, *TTY, *SOCK);
Used reasonably, vintage filehandles work perfectly well. I’m not sure the same can be said of those others. One needn’t resort to such games as this one:
to realize there’s a massively bigger bareword problem lurking right in front of us than that of filehandles alone. All the various multiple‐choice alternatives in my long code segment above should have by now made that starkly clear.no strict; no warnings; no less tricksy; foo(lish); his::bar(tab); silly->stuff; come on, please give up; package UNIVERSAL; sub AUTOLOAD { print "I am masquerading as $AUTOLOAD(@_)\n" }
In reply to Re^4: unquoted string error??!!
by tchrist
in thread unquoted string error??!!
by aji
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |