Fn, FnMut, FnOnce
คุณลักษณะของคลอเชอร์
Fn, FnMut, FnOnce เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
คุณลักษณะของ Closure
Closure ทุกตัวจะใช้คุณลักษณะหนึ่งอย่างหรือมากกว่าจากคุณลักษณะสามแบบโดยอัตโนมัติ ขึ้นอยู่กับวิธีที่ใช้ค่าที่จับไว้:
Fn— ยืมแบบไม่เปลี่ยนแปลงFnMut— ยืมแบบเปลี่ยนแปลงได้FnOnce— รับความเป็นเจ้าของและเรียกใช้ได้ครั้งเดียว
fn main() {
let x = 5;
let show = || println!("x is {}", x); // implements Fn
show();
show();
}Fn: การยืมแบบไม่เปลี่ยนแปลง
Closure ที่เพียง อ่าน ค่าที่จับไว้จะใช้คุณลักษณะ Fn และสามารถเรียกใช้ได้หลายครั้งโดยไม่เปลี่ยนแปลงสิ่งใด
fn main() {
let greeting = String::from("Hi");
let say = || println!("{}", greeting);
say();
say();
}FnMut: การยืมแบบเปลี่ยนแปลงได้
Closure ที่ เปลี่ยนแปลง ค่าที่จับไว้จะใช้คุณลักษณะ FnMut ตัวแปร closure เองต้องเป็น mut จึงจะเรียกใช้ได้
fn main() {
let mut count = 0;
let mut increment = || {
count += 1;
println!("count {}", count);
};
increment();
increment();
}FnOnce: การรับความเป็นเจ้าของ
Closure ที่ ย้าย ค่าที่จับไว้ออกจากสภาพแวดล้อมจะใช้คุณลักษณะ FnOnce และเรียกใช้ได้เพียงครั้งเดียว
fn main() {
let name = String::from("Ada");
let consume = move || {
let owned = name;
println!("consumed {}", owned);
};
consume();
}ลำดับชั้นของคุณลักษณะ
คุณลักษณะเหล่านี้มีลำดับชั้นดังนี้:
Fnทุกตัวเป็นFnMutและFnOnceด้วยFnMutทุกตัวเป็นFnOnceด้วย
ดังนั้น Fn จึงยืดหยุ่นที่สุด ส่วน FnOnce ยืดหยุ่นน้อยที่สุด
fn main() {
let value = 42;
let read = || value; // Fn, so also FnMut and FnOnce
println!("{}", read());
}การส่ง Fn ให้ฟังก์ชัน
ฟังก์ชันสามารถรับ closure ได้โดยระบุว่าต้องการคุณลักษณะใด ให้ใช้ชนิดทั่วไปพร้อมข้อกำหนดคุณลักษณะ
fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
f(x)
}
fn main() {
let double = |n| n * 2;
println!("{}", apply(double, 9));
}การรับ FnMut
หากฟังก์ชันของคุณต้องเปลี่ยนแปลงสถานะที่ถูกจับไว้ ให้กำหนดให้ใช้ FnMut และระบุพารามิเตอร์เป็น mut
fn call_twice<F: FnMut()>(mut f: F) {
f();
f();
}
fn main() {
let mut total = 0;
call_twice(|| total += 1);
// note: total is borrowed during the call
}การรับ FnOnce
เมื่อฟังก์ชันเรียกใช้ closure เพียงครั้งเดียวและอาจให้ closure ใช้ค่าจนหมด ให้กำหนดให้ใช้ FnOnce
fn run_once<F: FnOnce() -> String>(f: F) {
let result = f();
println!("{}", result);
}
fn main() {
let s = String::from("done");
run_once(move || s);
}คีย์เวิร์ด move
คีย์เวิร์ด move บังคับให้ closure รับ ความเป็นเจ้าของ ตัวแปรที่จับไว้ แทนการยืม
สิ่งนี้จำเป็นเมื่อ closure ต้องมีอายุยืนยาวกว่าขอบเขตที่สร้างขึ้น เช่น ในเธรด
fn main() {
let data = vec![1, 2, 3];
let printer = move || println!("{:?}", data);
printer();
}วิธีที่ Rust เลือกคุณลักษณะ
คุณไม่ต้องเลือกคุณลักษณะด้วยตนเอง คอมไพเลอร์จะตัดสินจากเนื้อหาของ closure:
- อ่านอย่างเดียว →
Fn - เปลี่ยนแปลงค่า →
FnMut - ย้ายค่าที่จับไว้ออกไป →
FnOnce
fn main() {
let mut log = Vec::new();
let mut record = |x: i32| log.push(x); // FnMut
record(1);
record(2);
println!("{:?}", log);
}การเลือกข้อกำหนดที่เหมาะสม
หลักทั่วไปมีดังนี้:
- รับ
Fnเมื่อจำเป็นต้องเรียกใช้และอ่านค่าเท่านั้น - รับ
FnMutเมื่อ closure เปลี่ยนแปลงสถานะ - รับ
FnOnceเมื่อเรียกใช้เพียงครั้งเดียวก็เพียงพอ
เลือกข้อกำหนดที่ยืดหยุ่นที่สุดและยังตรงกับความต้องการ
fn each<F: Fn(i32)>(items: &[i32], f: F) {
for &i in items {
f(i);
}
}
fn main() {
each(&[1, 2, 3], |n| println!("got {}", n));
}ตรวจสอบความเข้าใจ
จับคู่พฤติกรรมของ closure กับคุณลักษณะที่ตรงกัน
สรุปทบทวน
คุณลักษณะของ closure ทั้งสามแบบ:
Fn— ยืมแบบไม่เปลี่ยนแปลงและเรียกใช้ซ้ำได้FnMut— ยืมแบบเปลี่ยนแปลงได้และเปลี่ยนสถานะได้FnOnce— รับความเป็นเจ้าของและเรียกใช้ได้ครั้งเดียว
คอมไพเลอร์จะอนุมานคุณลักษณะให้ ส่วน move จะบังคับให้จับค่าโดยรับความเป็นเจ้าของ
fn main() {
let base = 5;
let adder = move |x: i32| x + base; // Fn, captures base by move
println!("{}", adder(10));
}คำถามที่พบบ่อย
บทเรียน “Fn, FnMut, FnOnce” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “Fn, FnMut, FnOnce” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “Fn, FnMut, FnOnce”
คุณลักษณะของคลอเชอร์ คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “Fn, FnMut, FnOnce” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม
ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การกำหนดฟังก์ชัน
- นิพจน์และคำสั่ง
- คลอเชอร์
- Fn, FnMut, FnOnce