2014-11-03 35 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; 
}