【问题标题】:Pattern matching in Perl ala HaskellPerl ala Haskell 中的模式匹配
【发布时间】:2011-11-22 23:57:51
【问题描述】:

在 Haskell(F#、Ocaml 等)中,我可以这样做:

sign x |  x >  0        =   1
       |  x == 0        =   0
       |  x <  0        =  -1

计算给定整数的符号。

这样可以简洁地表达一定的逻辑流程;我在 Perl 中遇到过其中一种流程。

我现在正在做的是

sub frobnicator
{
   my $frob = shift;
   return "foo" if $frob eq "Foomaticator";
   return "bar" if $frob eq "Barmaticator";
   croak("Unable to frob legit value: $frob received");
}

感觉没有表现力和丑陋。

此代码必须在 Perl 5.8.8 上运行,但我当然也对更现代的技术感兴趣。

【问题讨论】:

  • 我不知道你在找什么。除了ifreturn 之外的其他东西?你可以用这个做的不多。使用哈希?

标签: perl coding-style pattern-matching


【解决方案1】:

这是另一种可能的方法,它仍然有点罗嗦,但也许能更好地反映流程。 (在 Perl Best Practices 一书中,作者建议主要避免使用 if 的后缀形式,因为您需要一直扫描到右侧才能了解发生了什么。)如果这有助于突出显示条件,您可以添加括号.

sub sign
{
    my $x = shift;
    $x  > 0  and return  1;
    $x == 0  and return  0;
    $x  < 0  and return -1;
}

sub frobnicator
{
    my $frob = shift;

    $frob eq "Foomaticator" and return "foo";
    $frob eq "Barmaticator" and return "bar";

    croak("Unable to frob legit value: $frob received");
}

【讨论】:

  • 我没想到。 :) 这看起来最接近我正在寻找的东西。谢谢!
【解决方案2】:

你可以使用条件运算符:

sub frobnicator {
  my $frob = shift;
  return $frob eq 'Foomaticator' ? 'foo' :
         $frob eq 'Barmaticator' ? 'bar' :
         croak("Unable to frob legit value: $frob received");
}

它将你原来的例子变成这样的:

sub sign {
  my $x = shift;
  return $x < 0 ? -1 :
         $x > 0 ?  1 :
                   0 ;
}

你知道,这有点难看,但它抓住了重点:-)

【讨论】:

    【解决方案3】:
    sub sign { 
        my $x = shift;
        return $x <=> 0;
    }
    

    富有表现力?如果您知道"spaceship" operator 的作用,是的。如果没有,也没有那么多。我想说,一段 perl 代码的表现力如何完全取决于您对 perl 的熟悉程度。

    我必须说我不知道​​你在追求什么。对我来说,您示例中的代码非常清晰,一点也不难看。 perl 中总是有替代方案,那么如何:

    sub frobnicator
    {
       my $frob = shift;
       my %frobs = (
           Foomaticator    => "foo",
           Barmaticator    => "bar",
       );
       return $frobs{$frob} //  # If $frob is a defined key, return it
           croak("Unable to frob legit value: $frob received");
    }
    

    使用|| 而不是// 可能不太精确,但对旧版本的perl 可能更友好。

    【讨论】:

    • @EricStrom 是的,我一开始就是这样。 =)
    【解决方案4】:

    不管怎样,Perl 5.10 或更高版本为您提供:

    given

    ...这将允许:

    ...
    use feature qw( switch say);
    use Carp;
    sub frobnicator {
        my $frob = shift;
        given ($frob) {
            when ('Foomaticator') {
                return q(foo);
            }
            when ('Barmaticator') {
                return q(bar);
            }
            default {
                croak(qq(Unable to frob legit value: $frob received));
            }
        }
    }
    

    【讨论】:

    • 正则表达式匹配与字符串 eq 不同。你的意思是when ('Foomaticator')
    • 您需要致电use feature 'switch'use feature ':5.10' 启用此功能。
    • 我已经编辑了这个以反映 OP 对平等的要求,而不是正则表达式匹配,除了显示功能编译指示要求。分数很好。
    • 自 5.12(我认为)您可以在后缀中使用 when。所以你会得到return q(foo) when ('Foomaticator');,它更漂亮一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 2021-05-22
    • 1970-01-01
    相关资源
    最近更新 更多