简体   繁体   English

Perl ala Haskell中的模式匹配

[英]Pattern matching in Perl ala Haskell

In Haskell (F#, Ocaml, and others), I can do this: 在Haskell(F#,Ocaml等)中,我可以这样做:

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

Which calculates the sign of a given integer. 计算给定整数的符号。

This can concisely express certain logic flows; 这可以简洁地表达某些逻辑流程。 I've encountered one of these flows in Perl. 我在Perl中遇到了其中一种流程。

Right now what I am doing is 现在我正在做的是

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");
}

Which feels inexpressive and ugly. 感觉不好意思而且丑陋。

This code has to run on Perl 5.8.8, but of course I am interested in more modern techniques as well. 该代码必须在Perl 5.8.8上运行,但是我当然也对更现代的技术感兴趣。

Here's one other possible approach, which is still a bit wordy, but perhaps reflects the flow better. 这是另一种可能的方法,仍然有些罗word,但也许可以更好地反映流程。 (In the book Perl Best Practices, the author suggests mostly avoiding the postfix form of if because you need to scan all the way to the right to understand what is going on.) You could add parentheses if that helps to highlight the condition. (在《 Perl最佳实践》一书中,作者建议大多数情况下避免使用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");
}

You could use the conditional operator: 您可以使用条件运算符:

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

It turns your original example into something like: 它将您的原始示例变为:

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

Which, y'know, is a little ugly, but it gets the point across :-) 您知道,这有点丑陋,但它可以使您理解:-)

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

Expressive? 富有表现力? If you know what the "spaceship" operator does, yes. 如果您知道“太空飞船”操作员的工作,那么可以。 If not, not so much. 如果没有,那就不多了。 How expressive a piece of perl code feels to you is entirely dependent on your familiarity with perl, I would say. 我想说,一段Perl代码对您的表现力完全取决于您对Perl的熟悉程度。

I must say I've no idea what you are after. 我必须说我不知道​​你在追求什么。 To me, the code in your example is perfectly clear and not in the least ugly. 对我来说,您的示例中的代码非常清晰,而且一点也不难看。 There's always alternatives in perl, so how about: 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");
}

Slightly less precise, but perhaps more friendly to older perl versions is using || 略少精确,但也许更友好的较旧的perl版本使用|| instead of // . 代替//

For what it's worth, Perl 5.10 or later gives you: 对于Perl 5.10或更高版本,它具有以下优点:

given 给定

...which would allow: ...这将允许:

...
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));
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM