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

ส่งตัวแปรเข้าโคลเชอร์

คำอธิบาย

โดยค่าเริ่มต้นแล้ว 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) ลึกลงไปอีกหนึ่งระดับ