Perl 自适应微调子程序

Perl 自适应微调子程序,perl,reference,subroutine,Perl,Reference,Subroutine,通过这个例子,我想学习编写自适应子程序的最佳方法 我需要一个修剪文本的子程序(实际上,这是一个借口,我的子程序可以做任何其他事情) 为了更加通用,我希望我的子程序能够接受不同类型的参数: my@input=('A','B','C') my@trim=trim(@input) trim(\@输入) my$out=trim($input[0])返回“A” trim(\$input[0])修剪@input的第一个元素 trim(\@a、\@b、\@c)修剪每个字符串数组 my$out=trim(\@a

通过这个例子,我想学习编写自适应子程序的最佳方法

我需要一个修剪文本的子程序(实际上,这是一个借口,我的子程序可以做任何其他事情)

为了更加通用,我希望我的子程序能够接受不同类型的参数:

my@input=('A','B','C')

  • my@trim=trim(@input)

  • trim(\@输入)

  • my$out=trim($input[0])返回“A”

  • trim(\$input[0])修剪@input的第一个元素

  • trim(\@a、\@b、\@c)修剪每个字符串数组

  • my$out=trim(\@a,'a,'B')$out=(qw/A/B/);(行为有待讨论)

  • 以下是我目前的丑陋解决方案:

    sub trim {
        state $re = qr/^\s+|\s+$/m;
        my @a;
        for(@_) {
            if(ref eq 'SCALAR') { $$_ =~ s/$re//g;    }
            elsif(ref)          { trim(\$_) for(@$_); }
            else                { push @a, s/$re//gr; }
        }
        return \@a if @a > 1;
        return $a[0] if $a[0];
    }     
    
    这个实现是否有更好的解决方案支持我上面建议的不同类型的输入

    这个问题的主要原因与我的最后一个应用程序有关,在这个应用程序中,我携带的文本可以存储在字符串、字符串数组甚至散列中

    我想最好写下:

    trim(\@allmytexts);
    align(\@allmytexts, align=>'right');
    
    比:


    这个问题离题了,可能很快就要结束了

    然而,“在这样的子例程中要求这种类型的行为正确吗?”

    我会说不。我还不清楚您希望这个子程序对我面前的信息做什么,而且,如果不参考您的文档,我肯定会很难记住如何调用它,如果我一两天没有使用它的话。你会发现每个人都通过写作来使用它

    $string = trim($string)
    
    因为这就是他们所记得的

    看起来你自己也不清楚有些电话是干什么的,因此

    my $out = trim(\@a, ' A ', ' B'); $out = (qw/A B/); (behavior to be discussed)
    
    我猜想您已经习惯了一种具有不同传递机制的语言,类似这样的东西会很有用。在Perl中,所有内容都通过别名传递;因此,对
    @
    数组元素的操作与对实际参数的相同操作是等价的。这意味着,如果您将任何可写值作为参数传递,则子例程可以修改该值

    考虑到这一点,传递一个引用以指示它将被修改到位只不过是一个标志,指示子例程的行为方式,以及在使用该引用之前必须取消引用的限制

    问问你自己,你经常看到一个常用的库函数有这样的行为。例如,分别调用
    index
    rindex
    来执行非常类似的操作,现有的核心操作符
    lc
    trim
    尝试执行的操作相当相似,但它只接受一个参数并返回转换后的结果
    sprintf
    可以看作是
    printf
    的一个变体,只要它知道,如果文件句柄参数是对标量的引用,它应该将字符串放入变量中,而不是将其写入文件句柄。但它不是那样设计的

    我只能为一个已定义的问题提供另一种解决方案。你没有解释现实生活中的困难,因为你不确定你的
    trim
    应该做什么,我怀疑是否有人能帮助你改进它

    还有一件事要问你自己,当传递一个引用并修改该值时,返回值应该是什么?很明显,它应该在更改后返回值,但是,既然您正在编写自适应代码,那么如何根据调用是在标量、列表还是void上下文中更改返回值呢?或者,更好的做法是,将
    trim
    设置为

    my $n = q{               999                     };
    ++trim($n);
    

    这个问题离题了,可能很快就要结束了

    然而,“在这样的子例程中要求这种类型的行为正确吗?”

    我会说不。我还不清楚您希望这个子程序对我面前的信息做什么,而且,如果不参考您的文档,我肯定会很难记住如何调用它,如果我一两天没有使用它的话。你会发现每个人都通过写作来使用它

    $string = trim($string)
    
    因为这就是他们所记得的

    看起来你自己也不清楚有些电话是干什么的,因此

    my $out = trim(\@a, ' A ', ' B'); $out = (qw/A B/); (behavior to be discussed)
    
    我猜想您已经习惯了一种具有不同传递机制的语言,类似这样的东西会很有用。在Perl中,所有内容都通过别名传递;因此,对
    @
    数组元素的操作与对实际参数的相同操作是等价的。这意味着,如果您将任何可写值作为参数传递,则子例程可以修改该值

    考虑到这一点,传递一个引用以指示它将被修改到位只不过是一个标志,指示子例程的行为方式,以及在使用该引用之前必须取消引用的限制

    问问你自己,你经常看到一个常用的库函数有这样的行为。例如,分别调用
    index
    rindex
    来执行非常类似的操作,现有的核心操作符
    lc
    trim
    尝试执行的操作相当相似,但它只接受一个参数并返回转换后的结果
    sprintf
    可以看作是
    printf
    的一个变体,只要它知道,如果文件句柄参数是对标量的引用,它应该将字符串放入变量中,而不是将其写入文件句柄。但它不是那样设计的

    我只能为一个已定义的问题提供另一种解决方案。你没有解释现实生活中的困难,因为你不确定你的
    trim
    应该做什么,我怀疑是否有人能帮助你改进它

    还有一件事要问你自己,你应该做什么
    $x = trim($x);
    @a = map trim, @a;
    
    sub trim_i(_) { s/^\s+|\s+\z//g for $_[0] }
    
    trim_i($x);
    trim_i for @a;
    
    sub trim {
       wantarray
          ? map s/^\s+|\s+\z//rg, @_
          : $_[0] =~ s/^\s+|\s+\z//rg
    }
    
    $x = trim($x);
    @a = trim(@a);
    
    sub trim_i {
       s/^\s+|\s+\z//rg for @_;
    }
    
    trim_i($x);
    trim_i(@a);