2017-04-13 17 views
8

Giả sử tôi có một chuỗi nơi tôi biết điểm bắt đầu và điểm kết thúc và trình tạo là đơn giản. Tôi có thể làm cho nó lười biếng?Danh sách hữu hạn có thể lười biếng trong Perl 6 không?

my @b = 0 ... 3; 
say 'Is @b lazy? ' ~ @b.is-lazy; # Not lazy 

Tôi muốn kết hợp danh sách đã biết với chính nó một số lần không xác định nhưng không tạo toàn bộ danh sách ngay lập tức. Tôi muốn @cross để được lười biếng:

my @cross = [X] @b xx $n; 

Tôi biết tôi có thể làm được điều này thông qua các vấn đề khác đơn giản hoặc lập trình (và Perl tôi 5 Set::CrossProduct không chỉ đó), nhưng tôi tò mò nếu có một số cách đơn giản và có ý định mà tôi đang thiếu. Một số cách không liên quan đến việc tôi tự tính.

Là câu hỏi phụ, tính năng của chuỗi làm cho nó trở nên lười biếng là gì? Nó chỉ là điểm cuối? Có một chuỗi với một điểm cuối được biết đến mà vẫn có thể được lười biếng nếu máy phát điện có thể làm cho các giá trị vô hạn giữa? Tôi tự hỏi có bao nhiêu thông tin tôi phải xóa và thử một cái gì đó như thế này:

my $m = @*ARGS[0]; 
my @b = 0, * + $m ...^* > 3; 
say 'Is @b lazy? ' ~ @b.is-lazy; 
say '@b: ' ~ @b; 

Tuy nhiên, điều này không phải là lười biếng.

Trả lời

5

Phương pháp "lười biếng", theo ý kiến ​​của tôi, thực sự là một từ ngữ sai. Điều duy nhất nó nói, như cuonglm chỉ ra, là chỉ cần đi vào đó lặp đi lặp lại cơ bản tuyên bố là lười biếng. Nhưng vẫn là không có nghĩa là bất cứ điều gì, thực sự. Một trình vòng lặp có thể tạo ra các giá trị theo yêu cầu về mặt kỹ thuật, nhưng vẫn cho rằng nó không phải là lười. Và ngược lại.

Kiểm tra "lười biếng" được sử dụng nội bộ để ngăn chặn các trường hợp số lượng phần tử cần được biết trước (như .roll hoặc .pick): nếu Seq/iterator tuyên bố là lười, nó sẽ thắng ' t thực sự cố gắng, nhưng thất bại hoặc ném thay thế.

Điều duy nhất mà .lazy làm, được quấn vòng lặp của Seq vào một trình lặp khác mà thực hiện được cho là lười (nếu trình vòng lặp được cho là không lười). Và chắc chắn rằng nó sẽ không kéo bất kỳ giá trị trừ khi thực sự cần. Vì vậy, việc thêm .lazy không nói bất cứ điều gì về thời điểm các giá trị sẽ được tạo ra, chỉ khi chúng được phân phối. Và nó giúp kiểm tra logic dựa trên vòng lặp để xem cách chúng sẽ làm việc với một trình lặp mà tuyên bố là lười.

Vì vậy, hãy quay trở lại câu hỏi: nếu bạn muốn là chắc chắn rằng có điều gì đó lười biếng, bạn sẽ phải tự viết trình lặp. Có nói rằng, những tháng vừa qua tôi đã dành khá nhiều công sức để làm mọi việc càng lười càng tốt trong cốt lõi. Đáng chú ý là xx N vẫn không phải là lười biếng, mặc dù nó hiện sản xuất một Seq ngày nay. Làm cho nó lười biếng đã phá vỡ một số khán giả ở một số cấp độ sâu tôi đã không thể tìm ra chỉ được nêu ra. Nhìn về phía trước, tôi nghĩ bạn có thể chắc chắn rằng mọi thứ sẽ trở nên lười biếng như ý nghĩa nói chung, với khả năng chỉ ra sự ưa thích bộ nhớ trên CPU. Nhưng bạn sẽ không bao giờ có toàn quyền kiểm soát các nội trang: nếu bạn muốn kiểm soát hoàn toàn, bạn sẽ phải tự viết nó.

5

Vâng, bạn có thể sử dụng lazy method:

> my @b = (0 ... 3).lazy; 
[...] 
> say 'Is @b lazy? ' ~ @b.is-lazy; 
Is @b lazy? True 

Không có gì đặc biệt Seq mà làm cho nó được lười biếng, chỉ cần cơ bản của nó Iterator không là.

+0

Huh. Tôi chắc rằng tôi đã thử điều đó. Cảm ơn! –

1

Như đã được chỉ ra, is-lazy không thực sự có ý nghĩa gì cả.

Nhưng tôi chỉ muốn đề cập rằng có một số page on rakudo wiki cung cấp một vài manh mối về những gì bạn có thể mong đợi từ is-lazy.

1

Bạn có thể thực hiện:

my @b = 0 ... 3; 

lười biếng chỉ bằng cách thêm các từ khóa lazy ở đúng nơi, như thế này:

my @b = lazy 0 ... 3; 

Hoặc, như cuonglm chỉ ra, bạn có thể gọi phương thức của phạm vi, như sau:

my @b = (0 ... 3).lazy; 
Các vấn đề liên quan