ส่งตัวแปรเข้าโคลเชอร์
คำอธิบาย
โดยค่าเริ่มต้นแล้ว Closure ในภาษา Rust จะจับ (Capture) ตัวแปรจากสภาพแวดล้อมรอบข้างด้วยวิธีการยืมข้อมูล (Borrowing) หรือคุณอาจเลือกใช้คีย์เวิร์ด move หน้า Closure เพื่อโอนย้ายสิทธิ์ความเป็นเจ้าของ (Move) ตัวแปรทั้งหมดเข้ามาใน Closure ก็ได้ อย่างไรก็ดี บ่อยครั้งที่คุณต้องการย้ายตัวแปรเข้ามาเพียงแค่บางตัว, ต้องการส่งเข้ามาในรูปของสำเนาข้อมูล (Clone), ต้องการส่งผ่านการอ้างอิง (Reference) หรือต้องการแปลงรูปข้อมูลบางประการก่อนใช้งาน
แนวทางปฏิบัติที่แนะนำคือ การประกาศผูกตัวแปรซ้ำ (Variable Rebinding) ไว้ภายในบล็อกขอบเขต (Scope) แยกเฉพาะก่อนสร้าง Closure
ตัวอย่าง
เลือกใช้รูปแบบนี้:
#![allow(unused)]
fn main() {
use std::rc::Rc;
let num1 = Rc::new(1);
let num2 = Rc::new(2);
let num3 = Rc::new(3);
let closure = {
// `num1` is moved
let num2 = num2.clone(); // `num2` is cloned
let num3 = num3.as_ref(); // `num3` is borrowed
move || {
*num1 + *num2 + *num3;
}
};
}
แทนที่จะเขียนแบบนี้:
#![allow(unused)]
fn main() {
use std::rc::Rc;
let num1 = Rc::new(1);
let num2 = Rc::new(2);
let num3 = Rc::new(3);
let num2_cloned = num2.clone();
let num3_borrowed = num3.as_ref();
let closure = move || {
*num1 + *num2_cloned + *num3_borrowed;
};
}
ข้อดี
ตัวแปรที่ถูกโคลนหรือเตรียมไว้จะถูกจัดกลุ่มอยู่ร่วมกับนิยามของ Closure อย่างเป็นระเบียบ ทำให้เจตนาในการใช้งานมีความชัดเจน และตัวแปรชั่วคราวเหล่านั้นจะถูกทำลาย (Drop) ทิ้งทันทีเมื่อพ้นบล็อก แม้จะไม่ได้ถูกนำไปบริโภคจนหมดภายใน Closure ก็ตาม
Closure สามารถใช้ชื่อตัวแปรเดียวกับโค้ดแวดล้อมภายนอกได้ทันที โดยไม่ต้องตั้งชื่อตัวแปรยาวๆ ให้รกรุงรัง (เช่น ไม่ต้องตั้งชื่อว่า num2_cloned หรือ num3_borrowed)
ข้อเสีย
บล็อกโค้ดของ Closure จะมีการเยื้องบรรทัด (Indentation) ลึกลงไปอีกหนึ่งระดับ