美文网首页Raku Programming Language
Perl 6 - stackoverflow(2017.1.1)

Perl 6 - stackoverflow(2017.1.1)

作者: 焉知非鱼 | 来源:发表于2017-01-01 14:37 被阅读35次

    我想匹配任意一组单词,但是失败了,请问怎样才能正确地匹配到?

    my @a=<a b c d e f>;
    my $x="a1234567";
    say $x ~~ m/ @a.any /;
    

    Answer

    my @a = <a b c d e f>;
    my $x = "a1234567";
    say $x ~~ /@a/
    

    /@a//| @a/ 相同,它是最长的备选分支。对于备选分支,你可以使用 /|| @a/

    sub foo($x) {
      $x**2
    }
    
    my $alist = (1,2, &foo ... ^ * > 100);
    

    我想得到 (1 4 9 16 25 .. ) 而程序得到的是 (1 2 4 16 256)

    Answer:

    my @a = (1..*).map(* ** 2);  # using a Whatever-expression
    my @a = (1..*).map(&foo);    # using your `foo` function
    

    或者使用 Haskell/Python 那样的列表解析式:

    my @a = ($_ ** 2 for 1..*);  # using an in-line expression
    my @a = (foo $_ for 1..*);   # using your `foo` function
    

    另外还有一种方法:

    my @alist = {(++$)²} ... * > 70; # stop immediately after past 70
    say @alist; # [1 4 9 16 25 36 49 64 81]
    
    my @alist = {(++$)²} ...^ * > 70; # stop immediately before past 70
    say @alist; # [1 4 9 16 25 36 49 64]
    

    个人不推荐使用 $ 匿名变量的这种写法, 对于 new comer 不太友好。

    Is it possible to use junction to match any of the values in a junction? I want to match any of the values in an array. What is the proper way to do it?

    > my @a=<a b c>
    [a b c]
    > any(@a)
    any(a, b, c)
    > my $x=any(@a)
    any(a, b, c)
    > my $y = "a 1"
    a 1
    > say $y ~~ m/ $x /
    False
    > say $y ~~ m/ "$x" /
    False
    > my $x = any(@a).Str
    any("a", "b", "c")
    > say $y ~~ m/ $x /
    False
    > say $y ~~ m/ || $x /
    False
    > say $y ~~ m/ || @a /
    「a」
    

    Answer

    junctions 不该被插值到正则表达式中。它们应该被用在普通的 Perl 6 表达式中,特别是带有比较操作符的表达式(例如 eq):

    my @a = <x y z>;
    say    "y" eq any(@a);  # any(False, True, False)
    say so "y" eq any(@a);  # True
    

    要在正则表达式中匹配一个数组的任意值,就在正则表达式中写上那个数组名好了(以@开头)。默认地,这被插值为 | 备选分支(“longest match”),但是你也可以把他指定为 || 备选分支(“first match”)。

    my @a = <foo bar barkeep>;
    say "barkeeper" ~~ / @a /;     # 「barkeep」
    say "barkeeper" ~~ / || @a /;  # 「bar」
    

    我需要排序数组的数组, .sort 方法能不能按照内层数组的不同索引来排序呢?

    要排序的数组在一个更大的数组的外面:(birthday 是 'mmddyy' 格式的:)

    my @allRecords = [ [birthday1 firstName1 lastName1 [data1]
                       [birthday2 firstName2 lastName2 [data2] 
                       ...
                       [birthdayN firstNameN lastNameN [dataN] ];
    
    @allRecords.sort by itself sorts by birthdays.
    

    有什么好方法能按照 firstName 或 lastName 或 按照内层数组里面的数据来排序?

    Answer

    sort 方法接受一个可选的 sub 参数。如果元数是 1, 那么它使用返回值作为比较操作数;如果元数为 2, 那么你可以在两个元素之间手动作比较,两个元素的比较会返回 Less, Same, More

    拿你上面的例子来说,我们可以像这样按照 first name 进行排序:

    @allRecords.sort(*.[1])
    

    我们可以先按照 last name 再按照 first name 进行排序,然后按照 birthday 来做单独的比较,就像这样:

    @allRecords.sort(-> $a,$b {
        $a[2] cmp $b[2] || $a[1] cmp $b[1] || $a[0] cmp $b[0]
    });
    

    或者再次通过转换操作数:

    @allRecords.sort(*.[2...0]);
    

    变换 birthday 条目以至于我们能先按照 year 排序作为练习留给读者完成,但是其中一种方法是在合适的地方添加像这样的代码:

    .comb(2).list.rotate(-1).join
    

    你可以按照 lastname,firstname, birthday 这样的顺序排序:

    @a.sort: *[2...0]
    

    还有两个问题:

    • *.[1]*[1] 有什么区别?

    两者没有任何区别,但是前者可读性更好!

    • range 操作符和 ... 序列操作符有什么区别

    range 不能倒数, ... 可以倒数。

    在 Perl 6 中怎样找出列表中最大值的索引?

    Answer

    my @list = 1,2,9,6,9,5;
    @list.maxpairs; # [2 => 9 4 => 9]
    

    @list.maxpairs 用于获取索引和对应最大值的所有对儿。
    @list.pairs.max(*.value).key 用于仅获取单个索引。

    > @list.pairs.max(*.value).key
    2
    

    如何彻底地展平 Perl 6 的列表?这个问题不同于 How do I “flatten” a list of lists in perl 6?, 后者不是彻底的 flat。

    my @a  = 'a', ('b', 'c' );
    my @b  = ('d',), 'e', 'f', @a;
    my @c  = 'x', $( 'y', 'z' ), 'w';
    
    my @ab = @a, @b, @c;
    say "ab: ", @ab;
    
    my @f = @ab;
    
    @f = gather {
        while @f {
            @f[0].elems == 1 ??
                take @f.shift.Slip
                    !!
                @f.unshift( @f.shift.Slip )
            }
        }
    
    say "f: ", @f;
    

    这打印出:

    ab: [[a (b c)] [(d) e f [a (b c)]] [x (y z) w]]
    f: [a b c d e f a b c x y z w]
    

    但这不够简洁。一种可行的办法是使用:gather/take/deepmap:

    say gather @ab.deepmap(*.take)
    

    postcircumfix [] 操作符可用于多维下标来获取一组展平的叶子节点,直到特定的深度,尽管 “无限深度” 版本还没有实现:

    say @ab[*;*];     # (a (b c) (d) e f [a (b c)] x (y z) w)
    say @ab[*;*;*];   # (a b c d e f a (b c) x y z w)
    say @ab[*;*;*;*]; # (a b c d e f a b c x y z w)
    say @ab[**];      # HyperWhatever in array index not yet implemented. Sorry.
    
    • 避免容器化 (containerization)

    内置的 flat 函数能很好地展平深度嵌套的列表。问题是它不能落进 item 容器(Scalar)中。嵌套列表中非故意的 item 容器的常见来源有:

    • 数组(但不是列表)将其每个元素包装在一个新的 item 容器中,无论它之前有没有。
    • 如何避免:如果不需要 Array 提供的可变性,请使用列表的列表而不是数组的数组。使用绑定 := 可以用来代替赋值,将列表存储在@变量中,而不将其转换为数组
    my @a  := 'a', ('b', 'c' );
    my @b  := ('d',), 'e', 'f', @a;
    
    say flat @b;  # (d e f a b c)
    
    • $variables 是 item 容器。
    • 如何避免:当将列表存储在 $ 变量中,然后将其作为元素插入到另一个列表中时,使用 <> 来对它进行 decontainerize(解容器化)。当把 $ 变量传递给 flat 时, 父列表的容器也可以使用 | 绕过:
    my $a = (3, 4, 5);
    my $b = (1, 2, $a<>, 6);
    
    say flat |$b;  # (1 2 3 4 5 6)
    

    未完待续。。。

    相关文章

      网友评论

        本文标题:Perl 6 - stackoverflow(2017.1.1)

        本文链接:https://www.haomeiwen.com/subject/xxkivttx.html