Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

นำเข้าเส้นทางสู่ขอบเขตการทำงานด้วยคีย์เวิร์ด use (Bringing Paths into Scope with the use Keyword)

การที่ต้องพิมพ์เขียนเส้นทางเต็ม ๆ ทุกครั้งที่ต้องการเรียกใช้งานฟังก์ชันอาจทำให้รู้สึกไม่สะดวกและมีความซ้ำซากจำเจ ในรายการโค้ดที่ 7-7 ไม่ว่าเราจะเลือกใช้เส้นทางแบบสัมบูรณ์หรือแบบสัมพัทธ์ไปยังฟังก์ชัน add_to_waitlist ทุกครั้งที่เราต้องการเรียกใช้งานฟังก์ชัน add_to_waitlist เราก็จำเป็นต้องพิมพ์คำว่า front_of_house และ hosting นำหน้าอยู่ดี แต่ทว่าโชคดีที่ภาษานี้มีวิธีการทำให้ขั้นตอนนี้ง่ายขึ้น: เราสามารถสร้างทางลัด (shortcut) ไปยังเส้นทางใด ๆ ด้วยการใช้คีย์เวิร์ด use เพียงครั้งเดียว และหลังจากนั้นจะสามารถเรียกใช้ชื่อย่อที่สั้นลงได้ในทุกจุดในขอบเขตการทำงาน (scope) นั้น

ในรายการโค้ดที่ 7-11 เราจะทำการนำโมดูล crate::front_of_house::hosting เข้าสู่ขอบเขตการทำงานของฟังก์ชัน eat_at_restaurant ซึ่งจะส่งผลให้เราเหลือเพียงระบุเส้นทางสั้น ๆ แค่ hosting::add_to_waitlist ในการเรียกใช้งานฟังก์ชัน add_to_waitlist ภายใน eat_at_restaurant

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}

การใส่คำสั่ง use พร้อมระบุเส้นทางในขอบเขตการทำงานเปรียบเสมือนการสร้างลิงก์สัญลักษณ์ (symbolic link หรือ symlink) ในระบบไฟล์ข้อมูล ด้วยการเขียนคำสั่ง use crate::front_of_house::hosting ไว้ที่รากเครต ส่งผลให้ชื่อ hosting กลายเป็นชื่อที่ถูกต้องและเรียกใช้งานได้ในขอบเขตดังกล่าว เสมือนหนึ่งว่าโมดูล hosting นั้นได้รับการนิยามไว้ที่ระดับรากเครตโดยตรง และเส้นทางข้อมูลที่ถูกดึงเข้ามาใช้ผ่าน use ก็ยังคงผ่านการตรวจสอบความเป็นส่วนตัวตามปกติเหมือนกับเส้นทางอื่น ๆ

ข้อสังเกตคือ คีย์เวิร์ด use จะทำหน้าที่สร้างทางลัดเฉพาะสำหรับขอบเขตการทำงานเจาะจงที่มันปรากฏอยู่เท่านั้น ในรายการโค้ดที่ 7-12 ได้มีการย้ายฟังก์ชัน eat_at_restaurant เข้าไปอยู่ภายในโมดูลย่อยใหม่ชื่อ customer ซึ่งส่งผลให้มันอยู่คนละขอบเขตการทำงานกับคำสั่ง use ดังนั้นตัวฟังก์ชันจึงจะไม่สามารถคอมไพล์ผ่านได้

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;

mod customer {
    pub fn eat_at_restaurant() {
        hosting::add_to_waitlist();
    }
}

ข้อผิดพลาดจากคอมไพเลอร์แสดงให้เห็นว่าทางลัดดังกล่าวไม่มีผลใช้งานภายในโมดูล customer อีกต่อไป:

$ cargo build
   Compiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0433]: cannot find module or crate `hosting` in this scope
  --> src/lib.rs:11:9
   |
11 |         hosting::add_to_waitlist();
   |         ^^^^^^^ use of unresolved module or unlinked crate `hosting`
   |
   = help: if you wanted to use a crate named `hosting`, use `cargo add hosting` to add it to your `Cargo.toml`
help: consider importing this module through its public re-export
   |
10 +     use crate::hosting;
   |

warning: unused import: `crate::front_of_house::hosting`
 --> src/lib.rs:7:5
  |
7 | use crate::front_of_house::hosting;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default

For more information about this error, try `rustc --explain E0433`.
warning: `restaurant` (lib) generated 1 warning
error: could not compile `restaurant` (lib) due to 1 previous error; 1 warning emitted

สังเกตว่าจะมีข้อความแจ้งเตือน (warning) ระบุว่าคำสั่ง use นั้นไม่มีการเรียกใช้งานภายในขอบเขตของมันแล้วเช่นกัน! ในการแก้ไขปัญหานี้ ให้คุณโยกย้ายบรรทัดคำสั่ง use เข้าไปเขียนไว้ภายในโมดูล customer ด้วย หรือไม่ก็อ้างอิงถึงทางลัดในโมดูลหลักภายนอกด้วยการใช้เส้นทาง super::hosting จากภายในโมดูลย่อย customer แทน

การสร้างเส้นทางด้วย use ตามรูปแบบที่เหมาะสม (Creating Idiomatic use Paths)

จากรายการโค้ดที่ 7-11 คุณอาจจะสงสัยว่าทำไมเราจึงกำหนด use crate::front_of_house::hosting แล้วค่อยสั่งเรียก hosting::add_to_waitlist ใน eat_at_restaurant แทนที่จะระบุเส้นทางใน use ยาวไปจนถึงตัวฟังก์ชัน add_to_waitlist โดยตรงเพื่อให้ได้ผลลัพธ์แบบเดียวกัน ดังแสดงในรายการโค้ดที่ 7-13

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting::add_to_waitlist;

pub fn eat_at_restaurant() {
    add_to_waitlist();
}

แม้ว่าโค้ดทั้งในรายการโค้ดที่ 7-11 และรายการโค้ดที่ 7-13 จะสามารถทำงานได้สำเร็จลุล่วงเหมือนกัน แต่ทว่ารายการโค้ดที่ 7-11 ถือเป็นวิธีที่เหมาะสมตามหลักปฏิบัตินิยม (idiomatic way) ในการนำฟังก์ชันเข้าสู่ขอบเขตการทำงานด้วย use การนำโมดูลหลักของฟังก์ชันเข้าสู่ขอบเขตการทำงานหมายถึงเราต้องเขียนระบุชื่อโมดูลหลักนำหน้าฟังก์ชันเมื่อเรียกใช้ การทำแบบนี้จะทำให้โค้ดระบุได้อย่างชัดเจนว่าฟังก์ชันดังกล่าวไม่ได้ประกาศนิยามอยู่ภายในพื้นที่ปัจจุบันของมันเอง ในขณะที่ยังคงช่วยประหยัดการเขียนพิมพ์เส้นทางเต็ม ๆ ซ้ำซาก โค้ดในรายการโค้ดที่ 7-13 นั้นไม่ชัดเจนว่าตัวฟังก์ชัน add_to_waitlist ถูกนิยามไว้ที่ส่วนใดของระบบ

ในทางกลับกัน เมื่อคุณต้องการนำเข้า structs, enums หรือไอเท็มข้อมูลอื่น ๆ เข้ามาด้วย use วิธีปฏิบัติที่เหมาะสมคือการระบุเส้นทางไปจนถึงตัวไอเท็มชิ้นนั้น ๆ โดยตรงเลย รายการโค้ดที่ 7-14 แสดงวิธีการนำ struct HashMap จากไลบรารีมาตรฐานเข้าสู่ขอบเขตการทำงานของเครตฐานสองตามรูปแบบที่นิยมปฏิบัติกัน:

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert(1, 2);
}

ไม่มีเหตุผลเบื้องหลังที่สลักสำคัญมากนักสำหรับรูปแบบแนวคิดนี้ มันเป็นเพียงธรรมเนียมปฏิบัติร่วมกันที่พัฒนาขึ้นมา และนักเขียนโปรแกรมต่างเริ่มมีความคุ้นชินกับการอ่านและเขียนโค้ดภาษา Rust ในลักษณะนี้ไปแล้ว

ข้อยกเว้นเพียงอย่างเดียวของแนวทางปฏิบัตินี้คือ ยามที่เราจำเป็นต้องนำเข้าไอเท็มสองชิ้นที่มีชื่อพ้องกันเข้าสู่ขอบเขตการทำงานเดียวกันด้วยคำสั่ง use เนื่องจากระบบของ Rust ไม่อนุญาตให้ทำเช่นนั้นได้ รายการโค้ดที่ 7-15 แสดงวิธีการนำเข้าชนิดข้อมูล Result สองตัวที่มีชื่อเหมือนกันแต่มีโมดูลหลักต่างกันเข้าสู่ขอบเขตเดียวกัน และวิธีการเขียนเพื่อเรียกใช้งานพวกมัน:

use std::fmt;
use std::io;

fn function1() -> fmt::Result {
    // --snip--
    Ok(())
}

fn function2() -> io::Result<()> {
    // --snip--
    Ok(())
}

ดังที่เห็น การใช้โมดูลหลักนำหน้าจะช่วยคั่นแบ่งชนิดข้อมูล Result ทั้งสองประเภทออกจากกันได้ชัดเจน หากเราเขียนระบุเป็น use std::fmt::Result and use std::io::Result คู่กัน เราจะมีชนิดข้อมูล Result สองตัวปนอยู่ในขอบเขตเดียวกัน ซึ่งจะส่งผลให้ Rust ไม่สามารถจำแนกออกได้ว่าเราหมายถึงตัวใดเมื่อมีการเรียกคำว่า Result

การตั้งชื่อใหม่ให้กับชนิดข้อมูลด้วยคีย์เวิร์ด as (Providing New Names with the as Keyword)

มีอีกหนึ่งแนวทางในการแก้ไขปัญหาเรื่องชื่อที่พ้องกันยามนำเข้าสู่ขอบเขตเดียวกันผ่าน use คือ การพิมพ์เขียนคำสั่ง as ต่อท้ายเส้นทางเพื่อระบุชื่อเรียกใหม่เฉพาะที่ หรือ นามแฝง (alias) ให้แก่ชนิดข้อมูลนั้น ๆ รายการโค้ดที่ 7-16 แสดงวิธีการเขียนโค้ดในรายการโค้ดที่ 7-15 อีกแบบ โดยการเปลี่ยนชื่อเรียกของหนึ่งในชนิดข้อมูล Result ผ่านคีย์เวิร์ด as:

use std::fmt::Result;
use std::io::Result as IoResult;

fn function1() -> Result {
    // --snip--
    Ok(())
}

fn function2() -> IoResult<()> {
    // --snip--
    Ok(())
}

ในคำสั่ง use บรรทัดที่สอง เราได้เลือกตั้งชื่อใหม่ว่า IoResult ให้กับชนิดข้อมูล std::io::Result ซึ่งจะไม่ขัดแย้งพ้องกับชื่อ Result จากโมดูล std::fmt ที่เรานำเข้ามาด้วย ทั้งแนวทางในรายการโค้ดที่ 7-15 และรายการโค้ดที่ 7-16 ล้วนได้รับการยอมรับว่าถูกต้องและเหมาะสมตามหลักปฏิบัติ ดังนั้นการเลือกใช้งานจึงขึ้นอยู่กับความชอบส่วนบุคคลของคุณเอง!

การส่งออกชื่อไอเท็มซ้ำด้วย pub use (Re-exporting Names with pub use)

เมื่อเรานำเข้าชื่อไอเท็มสู่ขอบเขตการทำงานผ่านคีย์เวิร์ด use ชื่อดังกล่าวจะมีสถานะเป็นแบบส่วนตัวเฉพาะสำหรับขอบเขตที่ได้รับนำเข้าเท่านั้น เพื่ออนุญาตให้โค้ดภายนอกขอบเขตสามารถอ้างอิงและเรียกใช้ชื่อนั้นได้เสมือนว่าชื่อดังกล่าวได้รับการประกาศนิยามขึ้นภายในขอบเขตนั้นตั้งแต่แรก เราสามารถนำเอาคีย์เวิร์ด pub และ use มารวมพลังใช้งานร่วมกัน เทคนิคนี้เรียกว่า การส่งออกซ้ำ (re-exporting) เนื่องจากเราทำหน้าที่นำไอเท็มเข้าสู่ขอบเขตการทำงานพร้อมทั้งเปิดทางให้บุคคลอื่นสามารถดึงเอาไอเท็มนั้นไปใช้ในขอบเขตการทำงานของตนเองได้ด้วย

รายการโค้ดที่ 7-17 แสดงโค้ดในรายการโค้ดที่ 7-11 โดยเปลี่ยนคำสั่ง use ในโมดูลรากเครตให้กลายเป็น pub use

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}

ก่อนที่จะทำการแก้ไขเรื่องนี้ โค้ดภายนอกจำเป็นจะต้องเรียกใช้งานฟังก์ชัน add_to_waitlist ผ่านทางเส้นทางยาว ๆ อย่าง restaurant::front_of_house::hosting::add_to_waitlist() ซึ่งหมายความว่าจะต้องกำหนดให้โมดูล front_of_house เป็นแบบสาธารณะ (pub) ด้วย แต่เมื่อเรานำเอา pub use มาใช้ส่งออกโมดูล hosting ซ้ำจากระดับโมดูลรากแล้ว โค้ดภายนอกจะสามารถหันมาเรียกใช้ผ่านเส้นทางที่สั้นลงอย่าง restaurant::hosting::add_to_waitlist() ได้ทันที

การส่งออกซ้ำมีประโยชน์อย่างมากในยามที่โครงสร้างการจัดเก็บโค้ดภายในระบบของคุณ มีความแตกต่างไปจากมุมมองที่โปรแกรมเมอร์ผู้นำโค้ดของคุณไปใช้คาดเดาไว้ ตัวอย่างเช่น ในการเปรียบเทียบเรื่องร้านอาหารนี้ บุคลากรผู้ดูแลร้านจะคิดถึงโครงสร้างแบบ “หน้าร้าน (front of house)” และ “หลังร้าน (back of house)” แต่ทว่าลูกค้าที่เดินเข้าร้านคงจะไม่ได้คิดหรือมองเห็นโครงสร้างร้านอาหารในแง่มุมเหล่านั้น การเลือกใช้ pub use จึงช่วยให้เราสามารถออกแบบโครงสร้างโค้ดภายในรูปแบบหนึ่ง แต่เลือกแสดงผลให้ภายนอกเห็นเป็นโครงสร้างอีกรูปแบบหนึ่งได้ ซึ่งการทำเช่นนี้จะช่วยให้เครตห้องสมุดของเรามีความเป็นระเบียบเรียบร้อยทั้งสำหรับโปรแกรมเมอร์ผู้ทำหน้าที่พัฒนาห้องสมุด และโปรแกรมเมอร์ผู้นำห้องสมุดไปเรียกใช้งาน เราจะมาศึกษาตัวอย่างของการใช้ pub use และวิธีการส่งผลกระทบต่อเอกสารอ้างอิง (documentation) ของเครตของคุณเพิ่มเติมในหัวข้อ“ส่งออก API สาธารณะเพื่อความสะดวกในการใช้งาน” ในบทที่ 14

การใช้งานแพ็กเกจภายนอก (Using External Packages)

ในบทที่ 2 เราได้เคยร่วมกันพัฒนาโปรแกรมทายตัวเลขซึ่งมีระบบดึงเอาแพ็กเกจภายนอกที่ชื่อว่า rand มาช่วยในการสุ่มตัวเลข โดยในการเรียกใช้งาน rand ในโปรเจกต์ของเรานั้น เราได้พิมพ์เขียนบรรทัดด้านล่างนี้ลงในไฟล์ Cargo.toml:

rand = "0.10.1"

การใส่ชื่อ rand ในฟิลด์ dependencies ของไฟล์ Cargo.toml จะเป็นการแจ้งบอก Cargo ให้ทำหน้าที่ดาวน์โหลดแพ็กเกจ rand และโปรแกรมที่เกี่ยวข้องอื่น ๆ จากฐานข้อมูลกลาง crates.io และทำหน้าที่จัดเตรียม rand ให้พร้อมสำหรับใช้ในโปรเจกต์ของเรา

จากนั้น ในการนำคำประกาศของ rand เข้าสู่ขอบเขตการทำงานของแพ็กเกจเรา เราได้เขียนบรรทัดคำสั่ง use ที่เริ่มต้นด้วยชื่อของเครตคือ rand และระบุรายการไอเท็มย่อยที่เราต้องการนำเข้ามา ย้อนกลับไปพิจารณาเนื้อหาในส่วน“สร้างการสุ่มตัวเลข” ในบทที่ 2 เราได้ดึงเอาโมดูลย่อย rand::prelude เข้าสู่ขอบเขตการทำงานและสั่งเรียกใช้ฟังก์ชัน rand::rng:

use std::io;

use rand::prelude::*;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::rng().random_range(1..=100);

    println!("The secret number is: {secret_number}");

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: {guess}");
}

สมาชิกในชุมชนของภาษา Rust ได้มีการแบ่งปันผลงานแพ็กเกจต่าง ๆ มากมายไว้บนฐานข้อมูลกลาง crates.io ซึ่งการดึงเอาสิ่งเหล่านั้นเข้ามาใช้งานในโปรเจกต์ของคุณจะมีขั้นตอนการปฏิบัติที่คล้ายคลึงกัน คือ การระบุรายชื่อพวกมันลงในไฟล์ Cargo.toml ของคุณ และเขียนเรียกใช้ use เพื่อดึงเอาไอเท็มจากเครตเหล่านั้นเข้าสู่ขอบเขตการทำงาน

โปรดทราบว่าห้องสมุดมาตรฐาน std ก็มีสถานะเป็นเครตหนึ่งที่อยู่ภายนอกแพ็กเกจของเราเช่นเดียวกัน แต่เนื่องจากห้องสมุดมาตรฐานจะถูกแนบจัดส่งมาพร้อมกับตัวภาษา Rust ตั้งแต่แรกแล้ว เราจึงไม่มีความจำเป็นต้องไปเขียนแก้ไขไฟล์ Cargo.toml เพื่อดึงเอา std เข้ามาเพิ่ม แต่อย่างไรก็ตาม เรายังคงต้องเขียนระบุคำสั่ง use เพื่อดึงเอาไอเท็มข้อมูลต่าง ๆ ของมันเข้าสู่ขอบเขตงานของแพ็กเกจเรา ตัวอย่างเช่นการใช้ struct HashMap เราจะเขียนบรรทัดนี้:

#![allow(unused)]
fn main() {
use std::collections::HashMap;
}

นี่คือตัวอย่างของเส้นทางแบบสัมบูรณ์ที่ขึ้นต้นด้วยคำว่า std ซึ่งเป็นชื่อเฉพาะของเครตห้องสมุดมาตรฐาน

การใช้เส้นทางแบบซ้อนเพื่อจัดระเบียบรายการคำสั่ง use (Using Nested Paths to Clean Up use Lists)

หากโปรเจกต์ของเรามีการเรียกใช้งานไอเท็มข้อมูลหลายชิ้นที่มาจากเครตหรือโมดูลหลักตัวเดียวกัน การเขียนระบุบรรทัดคำสั่ง use แยกแยกบรรทัดกันจะใช้พื้นที่ในแนวตั้งของไฟล์ซอร์สโค้ดไปค่อนข้างมาก ตัวอย่างเช่น บรรทัดคำสั่ง use สองบรรทัดที่เราใช้ในโปรแกรมเกมทายตัวเลขในรายการโค้ดที่ 2-4 ที่ทำหน้าที่นำเข้าไอเท็มข้อมูลจาก std:

// --snip--
use std::cmp::Ordering;
use std::io;
// --snip--

use rand::prelude::*;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::rng().random_range(1..=100);

    println!("The secret number is: {secret_number}");

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: {guess}");

    match guess.cmp(&secret_number) {
        Ordering::Less => println!("Too small!"),
        Ordering::Greater => println!("Too big!"),
        Ordering::Equal => println!("You win!"),
    }
}

แต่ในทางกลับกัน เราสามารถเลือกใช้ระบบเส้นทางแบบซ้อน (nested paths) เพื่อดึงเอาไอเท็มเหล่านั้นเข้ามาสู่ขอบเขตงานได้พร้อมกันภายในบรรทัดเดียว โดยเราจะเขียนระบุส่วนของเส้นทางที่เป็นจุดร่วมกัน (common part) ตามด้วยโคลอนคู่ และวงเล็บปีกกาครอบกลุ่มไอเท็มย่อยที่มีความแตกต่างกันไว้ ดังที่แสดงในรายการโค้ดที่ 7-18

use rand::prelude::*;
// --snip--
use std::{cmp::Ordering, io};
// --snip--

fn main() {
    println!("Guess the number!");

    let secret_number = rand::rng().random_range(1..=100);

    println!("The secret number is: {secret_number}");

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

    let guess: u32 = guess.trim().parse().expect("Please type a number!");

    println!("You guessed: {guess}");

    match guess.cmp(&secret_number) {
        Ordering::Less => println!("Too small!"),
        Ordering::Greater => println!("Too big!"),
        Ordering::Equal => println!("You win!"),
    }
}

สำหรับโปรแกรมที่มีความใหญ่โตขึ้น การดึงเอาไอเท็มจำนวนมากที่สังกัดเครตหรือโมดูลเดียวกันเข้ามาด้วยระบบเส้นทางแบบซ้อนนี้ จะช่วยลดจำนวนบรรทัดคำสั่ง use ลงไปได้อย่างมหาศาลเลยทีเดียว!

เราสามารถใช้ประโยชน์จากเส้นทางแบบซ้อนในระดับใด ๆ ของเส้นทางก็ได้ ซึ่งจะมีประโยชน์มากเมื่อรวมคำสั่ง use สองบรรทัดที่มีเส้นทางย่อยร่วมกัน ตัวอย่างเช่น รายการโค้ดที่ 7-19 แสดงบรรทัดคำสั่ง use สองบรรทัด: บรรทัดแรกนำเข้า std::io และบรรทัดที่สองนำเข้า std::io::Write

use std::io;
use std::io::Write;

ส่วนเส้นทางที่เป็นจุดร่วมของทั้งคู่คือ std::io ซึ่งก็คือเส้นทางแบบเต็มในบรรทัดแรก ในการรวมทั้งสองเส้นทางนี้ให้กลายเป็นคำสั่ง use เพียงบรรทัดเดียว เราสามารถเขียนคำว่า self ในระบบเส้นทางซ้อนได้ ดังแสดงในรายการโค้ดที่ 7-20

use std::io::{self, Write};

คำสั่งบรรทัดนี้จะนำเข้าทั้ง std::io และ std::io::Write เข้าสู่ขอบเขตการทำงานพร้อมกัน

การนำเข้าไอเท็มต่าง ๆ ด้วยตัวดำเนินการดอกจัน (Importing Items with the Glob Operator)

หากเรามีความประสงค์ต้องการจะนำเข้าไอเท็มสาธารณะ ทั้งหมด ที่อยู่ภายในเส้นทางดังกล่าวเข้าสู่ขอบเขตการทำงาน เราสามารถระบุเส้นทางและตามหลังด้วยสัญลักษณ์ดอกจัน * (glob operator) ได้ดังนี้:

#![allow(unused)]
fn main() {
use std::collections::*;
}

บรรทัดคำสั่ง use นี้จะดึงเอาไอเท็มสาธารณะทั้งหมดที่ถูกนิยามไว้ใน std::collections เข้าสู่ขอบเขตการทำงานปัจจุบัน โปรดใช้ความระมัดระวังอย่างยิ่งในการเรียกใช้ตัวดำเนินการดอกจันนี้! เนื่องจากมันจะทำให้ตรวจสอบได้ยากขึ้นว่าชื่อของตัวแปรหรือฟังก์ชันใดบ้างที่ถูกนำเข้า และยากจะรู้ได้ว่าชื่อที่ถูกนำไปใช้ในโปรแกรมของคุณได้รับการประกาศขึ้นที่ใด นอกจากนี้ หากไลบรารีภายนอกมีการเปลี่ยนแปลงโครงสร้างคำจำกัดความ สิ่งที่คุณนำเข้ามาก็จะเปลี่ยนตามไปด้วย ซึ่งอาจส่งผลให้เกิดข้อผิดพลาดในการคอมไพล์ยามที่คุณอัปเกรดไลบรารีนั้นในอนาคต หากไลบรารีเพิ่มชื่อที่พ้องกันกับตัวแปรที่คุณประกาศใช้เองในขอบเขตเดียวกัน

ตัวดำเนินการดอกจันนี้มักถูกนำไปประยุกต์ใช้งานในขั้นตอนการเขียนชุดทดสอบ (testing) เพื่อดึงเอาทุกองค์ประกอบที่เกี่ยวข้องเข้ามาไว้ในโมดูล tests ซึ่งเราจะอธิบายเพิ่มเติมในหัวข้อ“วิธีการเขียนชุดทดสอบ” ในบทที่ 11 นอกจากนี้บางครั้งมันยังถูกนำไปใช้ร่วมกับรูปแบบโครงสร้าง prelude อีกด้วย สามารถเปิดอ่านรายละเอียดเพิ่มเติมเกี่ยวกับรูปแบบดังกล่าวได้ในเอกสารอ้างอิงของห้องสมุดมาตรฐาน