如何在 Perl 6 中编写“intersperse”函数
How to write an `intersperse` function in Perl 6
我在 Perl 6 中遗漏的一件事是 intersperse
函数 like Haskell has:
The intersperse function takes an element and a list and `intersperses' that element between the elements of the list.
例如这个:
intersperse <X Y>, (<a b>, <c d>, <e f>);
...应该 return 这个序列:
<a b>, <X Y>, <c d>, <X Y>, <e f>
所以我一直在尝试自己将其实现为自定义函数。
为了获得最大的可重用性,它应该:
- 支持任何类型的对象(包括List和Nil)作为元素。
- 不以任何方式改变元素的容器化。
- 不会展平或以其他方式影响元素的内部结构。
- Return 如果输入列表作为惰性序列给出,则为惰性序列,以便它可以用于无限序列,如
intersperse 42, 1..Inf
.
到目前为止我想出的是:
sub intersperse (\element, +list) {
((element xx *) Z list).map(|*)[1..*]
}
即:无限重复要穿插的元素,用list压缩,然后用map
到slip
每个元组,去掉zip加的嵌套层,不用将原来的元素压平,然后用一个数组下标去掉中间穿插元素的前导重复。
满足要求1-3,但不满足要求4,因为数组下标是eagerly操作(即完全迭代输入序列然后return是一个非惰性List) 并因此导致此函数在给定无限序列时挂起。
实现此功能以满足所有 4 个要求的好方法是什么?
我对我提出的解决方案不是特别满意,但他们走了:
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;
}
}
}
也许它会成为其他人想出更好的东西的灵感...
我在 Perl 6 中遗漏的一件事是 intersperse
函数 like Haskell has:
The intersperse function takes an element and a list and `intersperses' that element between the elements of the list.
例如这个:
intersperse <X Y>, (<a b>, <c d>, <e f>);
...应该 return 这个序列:
<a b>, <X Y>, <c d>, <X Y>, <e f>
所以我一直在尝试自己将其实现为自定义函数。 为了获得最大的可重用性,它应该:
- 支持任何类型的对象(包括List和Nil)作为元素。
- 不以任何方式改变元素的容器化。
- 不会展平或以其他方式影响元素的内部结构。
- Return 如果输入列表作为惰性序列给出,则为惰性序列,以便它可以用于无限序列,如
intersperse 42, 1..Inf
.
到目前为止我想出的是:
sub intersperse (\element, +list) {
((element xx *) Z list).map(|*)[1..*]
}
即:无限重复要穿插的元素,用list压缩,然后用map
到slip
每个元组,去掉zip加的嵌套层,不用将原来的元素压平,然后用一个数组下标去掉中间穿插元素的前导重复。
满足要求1-3,但不满足要求4,因为数组下标是eagerly操作(即完全迭代输入序列然后return是一个非惰性List) 并因此导致此函数在给定无限序列时挂起。
实现此功能以满足所有 4 个要求的好方法是什么?
我对我提出的解决方案不是特别满意,但他们走了:
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;
}
}
}
也许它会成为其他人想出更好的东西的灵感...