English 中文(简体)
在Perl,是否一项功能是暗中跳舞,或者我们能否期望打电话者使用地图?
原标题:In Perl, should a function do the wantarray dance, or can we expect the caller to use map?

On the (much appreciated) perlmonks site, I found the following snippet that trims the spaces from both sides of a string:

sub trim {
  @_ = $_ if not @_ and defined wantarray;
  @_ = @_ if defined wantarray;
  for (@_ ? @_ : $_) { s/^s+//, s/s+$// }
  return wantarray ? @_ : $_[0] if defined wantarray;
}

I don t understand why the author goes to all the trouble of checking wantarray almost every line. Why not just trim the string, and have the programmer use map when he is passing an array?

这三者之间有何区别,即:

my @test_array = (  string1 ,   string2 ,  string3  ,   string4  );
my @result = trim(@test_array);

Or a simple trim, called like this when one needs to trim an array:

my @test_array = (  string1 ,   string2 ,  string3  ,   string4  );
my @result = map { trim($_) } @test_array;
最佳回答

首先,如果你想把:

#e.1.
sub trim
{
    my @ar = @_;
    for (@ar) { s/^s+//, s/s+$// };
    return wantarray ? @ar : $ar[0];
}

Second, consider the above example and compare it with:

#e.2.
sub trim
{
    for (@_) { s/^s+//, s/s+$// };
}

区别是什么?

e.1. returns a new trimmed array, while e.2. modifies the original array.

奥基现在,原来的加密亚鲁廷做了什么?

如果你没有将回报价值分配到任何上,则自动地对原始阵列进行了修改。 如果你将回报值分配给另一个变量,则OR将原阵列留下来,并返回一个新的三毫米阵列

如何?

By checking to see if wantarray is defined at all. as long as the function is on the right hand side and the return value is assigned to a variable "defined wantarray" is true (regardless of scalar/array context).

问题回答

a. 打破这条线,因为它没有:

sub trim {
  @_ = $_ if not @_ and defined wantarray;
     # if there are no arguments, but a return value is requested
     # then place a copy of $_ into @_ to work on

  @_ = @_ if defined wantarray;
     # if the caller expects a return value, copy the values in @_ into itself 
     # (this breaks the aliasing to the caller s variables)

  for (@_ ? @_ : $_) { s/^s+//, s/s+$// }
     # perform the substitution, in place, on either @_ or $_ depending on
     # if arguments were passed to the function

  return wantarray ? @_ : $_[0] if defined wantarray;
     # if called in list context, return @_, otherwise $_[0]
}

I agree that the code gets a bit tedious with all of the wantarray checks, but the result is a function that shares a level of flexibility with Perl s builtin functions. The net result of making the function "smart" is to clean up the call site (avoiding looping constructs, temp variables, repetition, ...) which depending on the frequency the function is used can meaningfully improve code readability.

职能可以简化:

sub trim {
    @_ = @_ ? @_ : $_ if defined wantarray;

    s/^s+//, s/s+$// for @_ ? @_ : $_;

    wantarray ? @_ : shift
}

头两条线可以滚动为一线,因为它们正在采取相同的做法(签署为@_)与不同的来源价值相同。 没有必要在“外部<代码>返回......”中进行最后的“意向”检查,因为如果在真空环境中恢复价值,就没有任何进展。

但我可能把最后一行改为<代码>wantarray ? @_:pop,因为这样,它就象一个清单(斜体内的最后一点)。

一旦说到并做所有工作,便可使用以下称呼方式:

my @test_array = (  string1 ,   string2 ,  string3  ,   string4  );

my @result = trim @test_array;
my $result = trim $test_array[0];
trim @test_array; # in place trim

甚至仍然支持点火:

my @result = map trim, @test_array;

或大于:

my @result = map trim($_), @test_array;

可在与<代码>chomp类似的同时使用。

while (<$file_handle>) {
    trim; 
    # do something
}

人们对Perl的游泳现象的看法好坏参半。 我个人喜欢这样,当职能赋予我灵活性,使打电话者具有某种意义,而不是围绕职能僵硬的接口开展工作。

或许,提交人想要弄清标准<代码>chomp的功能。 没有必要在你自己的职能中这样做。

man perlfunc 
chomp VARIABLE 
chomp( LIST ) 
chomp 

[......] 如果你填写一份清单,每个要素都是一致的。 [......]

Note that this is exactly how Text::Trim is implemented. See its description on various use-cases. Plays with wantarray allows to distinguish various contexts and implement different semantics for each.

在个人方面,我更喜欢单一语种,因为更容易理解和使用。 我将避免使用<代码>$_ 缺省变量或根据Nylon Smile实例1进行改动。





相关问题
Why does my chdir to a filehandle not work in Perl?

When I try a "chdir" with a filehandle as argument, "chdir" returns 0 and a pwd returns still the same directory. Should that be so? I tried this, because in the documentation to chdir I found: "...

How do I use GetOptions to get the default argument?

I ve read the doc for GetOptions but I can t seem to find what I need... (maybe I am blind) What I want to do is to parse command line like this myperlscript.pl -mode [sth] [inputfile] I can use ...

Object-Oriented Perl constructor syntax and named parameters

I m a little confused about what is going on in Perl constructors. I found these two examples perldoc perlbot. package Foo; #In Perl, the constructor is just a subroutine called new. sub new { #I ...

Where can I find object-oriented Perl tutorials? [closed]

A Google search yields a number of results - but which ones are the best? The Perl site appears to contain two - perlboot and perltoot. I m reading these now, but what else is out there? Note: I ve ...