Re: Reliably simulating 5.10 say()
by BrowserUk (Patriarch) on Feb 08, 2015 at 14:28 UTC
|
How about: sub say{ print @_ ? @_ : $_, "\n"; }
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
| [reply] [d/l] |
|
|
ok, that works, thanks.
But it leaves me worried that $_ is being used in say() as a global...
...or am I needlessly worried here? All the best practices talk about not using $_ since it's a global, and your suggestion uses $_. So the question is, is that $_ referenced in the say() sub a global from the implicit $_ in the mainline loop, or not...?
| [reply] |
|
|
But it leaves me worried that $_ is being used in say() as a global...
You can't "use as a global", you can just "use a global", and you're the one who asked to use $_.
So the question is, is that $_ referenced in the say() sub a global from the implicit $_ in the mainline loop, or not...?
Yes, because $_ is a global. Actually, it's a "super global", meaning "$_" refers to the same variable ($::_) no matter which package you're in.
Note: It is possible to make $_ a lexical, but that feature was also introduced in 5.10, it's experimental, and I don't think it will survive. (A step was already taken by core to avoid using it.)
So what you get is:
BEGIN {
if ($] < 5.010) {
*say = sub { local $\ = "\n"; print @_ ? @_ : $_ };
} else {
require feature;
feature->import('say');
}
}
There's probably a module that does that.
| [reply] [d/l] [select] |
|
|
But it leaves me worried that $_ is being used in say() as a global...
That's what $_ is; a global; and it's exactly what the real say does, along with a raft of other built-ins.
But it's a read-only reference, so it cannot harm anything.
So the question is, is that $_ referenced in the say() sub a global from the implicit $_ in the mainline loop, or not...?
I cannot parse the highlighted bit of that sentence.
Perhaps this will satisfy: There is only one $_ at any given time. It is the global $_.
Sometimes it is localised implicitely by some constructs (eg. for, while) and sometimes explicitly by user code; but all that means is that a copy of the previous value is kept somewhere and gets restored once the localisation ends.
Whenever you use $_; you get its current value, regardless of whether it has been localised in one or many previous scopes.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
| [reply] |
|
|
|
|
The best practice of not using globals is like "don't use goto" or "don't do drugs" - the rule exists because the majority of people abuse them. This is one of the cases where you know what you are doing and why - you're not defining a new global, instead you want to use $_ for its intended purpose. So don't worry :-)
The only minor caveat about $_ might be if someone were using the experimental lexical $_, introduced in Perl 5.10 and made experimental due to various problems in 5.18:
sub foo { print "<$_>\n" }
for (qw/a b/) {
foo;
for my $_ (qw/x y/) {
foo;
}
}
__END__
Use of my $_ is experimental at - line 4.
<a>
<a>
<a>
<b>
<b>
<b>
But that's a case of "the user got what they were asking for", plus there's the warning about it being experimental.
P.S. Have you seen Perl6::Say and Say::Compat? And by the way, the former simply does this in its source: @_ = $_ unless @_; | [reply] [d/l] [select] |
Re: Reliably simulating 5.10 say()
by Athanasius (Archbishop) on Feb 08, 2015 at 14:12 UTC
|
Hello hlc, and welcome to the Monastery!
This is one case where prototypes are actually useful. From perlsub#Prototypes:
As the last character of a prototype, or just before a semicolon, a @ or a %, you can use _ in place of $: if this argument is not provided, $_ will be used instead.
Hence:
#! perl
use strict;
use warnings;
sub say (_) # <-- ADD THIS
{
print @_, "\n";
}
my @a = qw(1 2 3);
say for @a;
Output:
0:16 >perl 1151_SoPW.pl
1
2
3
0:16 >
Hope that helps,
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
|
|
Yes, you’re right:
Pity. :-(
| [reply] |
|
|
Unfortunately, the _ prototype was added in 5.10 (check perl5100delta), the same version where say was added.
| [reply] |
|
|
sub say (_) # <-- ADD THIS
{
local $\ = "\n";
print @_;
}
| [reply] [d/l] |
|
|
Thanks, but that gives me the error:
Not enough arguments for main::say at a.pl line 10, near "say foreach
+"
Malformed prototype for main::say: _ at a.pl line 13.
| [reply] [d/l] |
|
|
Perhaps it is a relatively new feature. Which version of Perl are you running?
The same code works for me in Perl 5.14.
Update: I did not see it before I posted the above, but several people have responded below that it is a feature that was introduced in version 5.10.
| [reply] |
|
|
It works perfectly for me. Please show the exact code that you tested and gave this error.
| [reply] |
|
|
Re: Reliably simulating 5.10 say()
by CountZero (Bishop) on Feb 08, 2015 at 15:39 UTC
|
Or use Say::Compat.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James My blog: Imperial Deltronics
| [reply] |