2014-11-03 37 views
2

写这个是否正确?

sub foobar { 
    local $_ = $_[0] if @_; 
    s/foo/bar/; 
    $_; 
} 

的想法是采取$_如果没有给出chomp参数做。然后,我可以写

foobar($_); 

&foobar; 
+0

缺少最终的'/'在替代。 – choroba 2014-11-03 09:52:46

+0

谢谢,我忘了:) – nowox 2014-11-03 09:59:25

+0

此外,使用[警告](http://p3rl.org/warnings)告诉你:'标量值@_ [0]更好写成$ _ [0]'。 – choroba 2014-11-03 10:07:05

回答

3

这是不正确的,没有。麻烦的是,你不能有条件地local - 它是本地化的,或者不是。

而是这样做的,我的建议是您本地化它,然后有条件地复制从@_

local $_ = $_; 
$_ = shift if @_; 

这样,$_总是局部的,但只能有条件地从第一位置参数复制如果存在的话。

+1

或'local $ _ = @_?转移:$ _' – 2014-11-03 11:31:13

+0

Ohyes;那也可以工作 – LeoNerd 2014-11-03 11:32:22

+0

Re“问题是你不能有条件的在本地工作”,真的吗?你愿意支持吗? – ikegami 2014-11-03 15:15:11

0

我必须问 - 你究竟想在这里完成什么?

它看起来像你想要一个像一些'builtins'像chomp一样工作的子。我会建议这是不好的做法。

  • 意外的事情使代码维护更困难。维持你的代码的下一个人应该永远不要想'wtf?'。
  • 弄乱'内置'变量 - 例如重新赋值给$_会产生非常奇怪的后果。
  • 如果有人看到你的子程序调用,他们将不得不去看看它是干什么的。这几乎就是一个不好的子程序。

问题:$_的范围是什么?

答案:“它很复杂”,因为它是全球性的,但有时它是隐式地本地化的。有时它本身并不是一个变量,它是一个别名,通过修改它可以改变原来的。

这意味着从代码可维护性的角度来看,这只是一个坏消息。

来源:http://perldoc.perl.org/perlvar.html#General-Variables

$_ is by default a global variable. However, as of perl v5.10.0, you can use a lexical version of $_ by declaring it in a file or in a block with my. Moreover, declaring our $_ restores the global $_ in the current scope. Though this seemed like a good idea at the time it was introduced, lexical $_ actually causes more problems than it solves. If you call a function that expects to be passed information via $_ , it may or may not work, depending on how the function is written, there not being any easy way to solve this. Just avoid lexical $_ , unless you are feeling particularly masochistic. For this reason lexical $_ is still experimental and will produce a warning unless warnings have been disabled. As with other experimental features, the behavior of lexical $_ is subject to change without notice, including change into a fatal error.

+0

我同意你的观点,但为什么chomp会这样工作? – nowox 2014-11-03 12:35:54

+2

遗留原因。 Perl最初是以这种方式构建的,改变它会破坏很多代码。 – Sobrique 2014-11-03 12:39:06

+0

muh,'map trim,@ a'对我来说听起来不是一个坏习惯。有时候它是有道理的。 – ikegami 2014-11-03 16:36:05

3

如果你想通过使用一个外$ _的函数,你可以使用 “_” 原型:

# dolund.pl 
# 
use strict; 

sub dolund (_) 
     { my $p1 = $_[0]; 
      print "passed parameter is $p1\n"; 
      } 

dolund 12;  # prints 12 

my $fred = 21; # prints 21 
dolund $fred; 

$_ = 'not 12'; 
dolund;   # prints "not 12" 

Obiously,你可以如果你喜欢,请使用$p1=~ s/foo/bar/;。我只是想证明$_的隐含传球。

3

local $_ = ... if @_;只会本地化$_如果子接收到一个参数,这意味着它不会保护呼叫者的$_是子没有收到参数,这不是你想要的。

最小的修复

sub sfoobar { 
    local $_ = @_ ? shift : $_; 
    s/foo/bar/; 
    return $_; 
} 

但你不妨在这一点上使用命名变量。

sub sfoobar { 
    my $s = @_ ? shift : $_; 
    $s =~ s/foo/bar/; 
    return $s; 
} 

5.10+介绍了_原型。

sub sfoobar(_) { 
    my ($s) = @_; 
    $s =~ s/foo/bar/; 
    return $s; 
} 

5.14+介绍s///r

sub sfoobar(_) { 
    return $_[0] =~ s/foo/bar/r; 
}