Co

Collect در Rust

{one: "۱ تمرین", other: "%{count} تمرین"}

درباره‌ی Collect

برای درک تابع collect مهم است بدانید که از آن برای حل کردن یک «تکرارگر» استفاده می‌شود. به یاد بیاورید که تکرارگر دنباله‌ای از عناصر است که می‌توان آن را با تکرارگرهای دیگر زنجیره کرد. تکرارگرها «تنبل» هستند؛ یعنی تا زمانی که کدی را که تکرارگر را مصرف می‌کند فراخوانی نکنید، اجرا نمی‌شوند. چنین کدهایی شامل حلقه‌های for و انطباق‌دهنده‌های مصرف‌کننده می‌شوند. انطباق‌دهنده‌های مصرف‌کننده همه‌ی عناصر تکرارگر را پردازش می‌کنند تا نوعی خروجی تولید کنند.

collect یکی از همین انطباق‌دهنده‌های مصرف‌کننده است که می‌توان از آن برای تولید نمونه‌ای از هر نوعی استفاده کرد که trait FromIterator را پیاده‌سازی می‌کند. این trait برای همه‌ی مجموعه‌های کتابخانه‌ی استاندارد پیاده‌سازی شده است. چون FromIterator برای انواع زیادی پیاده‌سازی شده، باید به Rust بگویید چه نوع مجموعه‌ای می‌خواهید. برای نمونه، اگر بخواهیم از یک برش رشته‌ای یک Vec<char> بسازیم، می‌توانیم نوع را در فراخوانی collect وارد کنیم، به این شکل

    let my_chars = "Hello, World!".chars().collect::<Vec<char>>();
// since the item type of the `String::chars()` iterator can be inferred to be `char`, we can omit that information
// let my_chars = "Hello, World!".chars().collect::<Vec<_>>();

دو دونقطه و براکت‌های زاویه‌دار بیرونی (یعنی ::<_>) به turbofish معروف‌اند. در این مورد، turbofish نحوه‌ی نگارش پرسروصداتری است از آنچه لازم داریم. با مشخص کردن نوع روی خود متغیر، collect می‌تواند با سروصدای نگارشی کمتری استنتاج کند که چه مجموعه‌ای باید بسازد.

    let my_chars: Vec<char> = "Hello, World!".chars().collect();
// or
// let my_chars: Vec<_> = "Hello, World!".chars().collect();

اگر Stringای با کاراکترهای برعکس‌شده می‌خواستیم، می‌توانستیم این‌طور انجام دهیم

    let rev_chars: String = "Hello, World!".chars().rev().collect();

استنتاج نوع در Rust آن‌قدر قدرتمند است که گاهی نیازی به آوردن صریح نوع در خط نداریم:

fn get_reversed_chars(phrase: &str) -> Vec<char> {
    phrase.chars().rev().collect()
}

نوع بازگشتی تابع get_reversed_chars باعث می‌شود تابع collect استنتاج کند چه مجموعه‌ای را باید برگرداند. اما اینجا باید Vec<char> را مشخص کنیم و نه Vec<_>، چون Rust برای امضای توابع استنتاج نوع انجام نمی‌دهد. این کار برای این است که کسی که کد را می‌خواند بتواند سریع بفهمد یک تابع چه نوع‌هایی را می‌گیرد و چه نوع‌هایی را برمی‌گرداند.

ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود