Một giải pháp barebones
Hãy bắt đầu với một giải pháp rất đơn giản để in một ý chính của trình tự. Nó không giải quyết các chi tiết cụ thể mà bạn đã thêm vào câu hỏi của mình nhưng đó là điểm khởi đầu tốt:
sub seq-range-gist ( @seq ) {
my @pairs = @seq.pairs;
join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}
Không giống như .kv
, chuyển đổi invocant của nó thành dạng key1, value1, key2, value2, key3, value3, ...
, tức là 6 phần tử nếu invocant của nó chứa 3 phần tử, .pairs
chuyển đổi invocant của nó thành dạng key1 => value1, key2 => value2, key3 => value3, ...
.
Tôi đã sử dụng .pairs
thay vì .kv
một phần vì điều đó có nghĩa là tôi chỉ có thể sử dụng ».gist
sau này trong mã để dễ dàng có được một key1 => value1
màn hình đẹp cho từng thành phần. Chúng tôi sẽ sửa đổi điều đó dưới đây nhưng đây là một khởi đầu thành ngữ tốt.
Các cuộc gọi .head
và cách .tail
gọi là cách thành ngữ để tạo danh sách nhỏ các thành phần N đầu tiên và cuối cùng từ một danh sách bất khả xâm phạm (miễn là nó không lười biếng; nói thêm về điều đó trong một mo).
Đưa ra giải pháp ban đầu này, say seq-range-gist (0,1 ... Inf)[^10]
hiển thị:
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
Tiếp theo, chúng tôi muốn có thể "chỉ bỏ phần tử đầu tiên ... từ đầu ra được in". Thật không may say seq-range-gist (0,1 ... Inf)[1..9]
hiển thị:
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
Chúng tôi muốn số ở bên trái của số =>
để giữ lại số thứ tự của chuỗi ban đầu. Để cho phép điều này, chúng tôi chia chuỗi bên dưới khỏi phạm vi mà chúng tôi muốn trích xuất. Chúng tôi thêm một tham số / đối số thứ hai @range
và nối [@range]
vào dòng thứ hai của phụ:
sub seq-range-gist ( @seq, @range ) {
my @pairs = @seq.pairs[@range];
Bây giờ chúng ta có thể viết say seq-range-gist (0,1 ... Inf), 1..9
để hiển thị:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
Trong câu hỏi của bạn, bạn đã sử dụng định dạng aINDEX = VALUE
chứ không phải INDEX => VALUE
. Để cho phép tùy chỉnh ý chính, chúng ta thêm một &gist
tham số / tham số thường trình thứ ba và gọi nó thay vì .gist
phương thức dựng sẵn :
sub seq-range-gist ( @seq, @range, :&gist ) {
my @pairs = @seq.pairs[@range];
join "\n", @pairs.head(3)».&gist, '...', @pairs.tail(2)».&gist
}
Lưu ý làm thế nào các cách gọi "phương thức" trong cơ thể của seq-range-gist
phụ bây giờ .&gist
, không .gist
. Cú pháp .&foo
gọi một phụ &foo
(thường được gọi bằng cách chỉ viết foo
), truyền vào bên trong của bên trái .
dưới dạng một$_
đối số đối số cho phụ.
Cũng lưu ý rằng tôi đã tạo &gist
tham số được đặt tên bằng cách đặt trước tham số đó bằng a :
.
Vì vậy, bây giờ say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }
hiển thị:
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
Thêm đánh bóng
Phần còn lại của câu trả lời này là tài liệu thưởng cho những độc giả quan tâm đến việc đánh bóng.
say seq-range-gist (0, 1, 2, 3), ^3
hiển thị:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
Giáo sư. Và ngay cả khi có nhiều cặp hơn đầu và đuôi kết hợp, do đó, ít nhất chúng tôi đã không nhận được các dòng lặp đi lặp lại, vẫn sẽ vô nghĩa khi sử dụng head, ..., tail
phương pháp tiếp cận chỉ với một hoặc hai yếu tố. Hãy thay đổi tuyên bố cuối cùng trong cơ thể phụ để loại bỏ các vấn đề sau:
join "\n",
@pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
Tiếp theo, sẽ thật tuyệt nếu phụ làm điều gì đó hữu ích nếu được gọi mà không có phạm vi hoặc ý chính. Chúng tôi chủ yếu có thể khắc phục điều đó bằng cách đưa ra @range
và &gist
các tham số phù hợp mặc định:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
Nếu @seq
là không lười biếng , sau đó @range
mặc định là đầy đủ các @seq
. Nếu @seq
là vô hạn (trong trường hợp đó cũng là lười biếng), thì mặc định tối đa 100 là ổn. Nhưng nếu @seq
lười biếng nhưng mang lại ít hơn 100 giá trị được xác định thì sao? Để bao gồm trường hợp này, chúng tôi thêm .grep: *.value.defined
vào @pairs
tuyên bố:
my @pairs = @seq.pairs[@range].grep: *.value.defined;
Một cải tiến đơn giản khác sẽ là các tham số đầu và đuôi tùy chọn, dẫn đến một giải pháp đánh bóng cuối cùng:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:$head = 3,
:$tail = 2,
:&gist = { .gist }
) {
my @pairs = @seq.pairs[@range].grep: *.value.defined;
join "\n",
@pairs <= $head + $tail + 2
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
}