如何在Perl 6

时间:2016-09-01 08:00:19

标签: list perl6 lazy-sequences

我在Perl 6中遗漏的一件事是intersperse函数like Haskell has

  

intersperse函数接受一个元素和一个列表,并在列表元素之间“穿插”该元素。

E.g。这样:

intersperse <X Y>, (<a b>, <c d>, <e f>);

...应该返回这个序列:

<a b>, <X Y>, <c d>, <X Y>, <e f>

所以我一直在尝试将它作为自定义函数实现。 为了最大限度地重复使用,它应该:

  1. 支持任何类型的对象(包括List和Nil)作为元素。
  2. 不以任何方式改变元素的容器化。
  3. 不以任何方式压扁或以其他方式影响元素的内部结构。
  4. 如果输入列表以延迟序列的形式给出,则返回一个惰性序列,以便它可以用于无限序列,如intersperse 42, 1..Inf
  5. 到目前为止,我想出的是:

    sub intersperse (\element, +list) {
        ((element xx *) Z list).map(|*)[1..*]
    }
    

    即:无限重复要穿插的元素,将其与列表一起压缩,然后使用mapslip每个元组,以便删除由zip添加的嵌套层,而不会展平原始元素,然后使用数组下标去除散布元素的前导重复。

    它满足要求1-3,但不满足4,因为数组下标急切地操作(即完全迭代输入序列,然后返回非惰性列表),从而导致此函数当给出无限序列时挂起。

    实现此功能以满足所有4项要求的好方法是什么?

1 个答案:

答案 0 :(得分:10)

我对我提出的解决方案并不是特别满意,但是他们走了:

sub intersperse (\element, +list) {
    map { ((element xx *) Z list).map(|*)[$_] },
        1..(list.is-lazy ?? Inf !! list.elems * 2 - 1);
}
sub intersperse (\element, +list) {
    gather for list {
        FIRST .take, next;
        take slip element, $_;
    }
}
sub intersperse (\element, +list) {
    list.map({ slip element, $_ }) does role {
        method iterator {
            my \it = callsame;
            it.pull-one;
            it;
        }
    }
}

也许它会为其他人提供更好的东西......