åã ããæã£ã¦ããã®ã ããRustã®ã¯ãã¼ã¸ã£ã¨ãããååãã«ã¯éåæããã£ãããªããªããã¯ãã¼ã¸ã£ã¨è¨ãã®ã¯æ¬æ¥ãã ã®é¢æ°ã®ãã¨ã示ãããã§ã¯ãªãããã ã
ã ãã¯ãã¼ã¸ã£ã«ã¤ãã¦èª¿ã¹ã¦ã¿ã¦ãæ¹ãã¦ãRustã®ã¯ãã¼ã¸ã£ã¯å³å¯ã«ã¯ã¯ãã¼ã¸ã£ã§ã¯ãªããã¨ãããã¨ãã¯ã£ããããã®ã§ãä»åã¯Rustã®ã¯ãã¼ã¸ã£ã¯ã¯ãã¼ã¸ã£ã§ã¯ãªãã¨ãããã¨ã説æãã¦ãããã¨æãã
- Rustã®ãã¯ãã¼ã¸ã£ãã¨ã¯
- ãããããã¯ãã¼ã¸ã£ãã®å®ç¾©ã¨ã¯ï¼
- ãªãRustã®ã¯ãã¼ã¸ã£ã¯ãã¯ãã¼ã¸ã£ãã§ã¯ãªãã®ãï¼
- Rustã®ã¯ãã¼ã¸ã£ã§çä¼¼çãªã¯ãã¼ã¸ã£ãä½ã
Rustã®ãã¯ãã¼ã¸ã£ãã¨ã¯
ã¾ãã¯ç°¡åã«Rustã®ãã¯ãã¼ã¸ã£ãï¼ä»¥ä¸Rustã¯ãã¼ã¸ã£ï¼ã«ã¤ãã¦èª¬æãã¦ããããRustã¯ãã¼ã¸ã£ã¯ä»¥ä¸ã®ããã«æ¸ããã¨ã§å®ç¾©ã§ããã
let closure = |arg| arg + 1i32;
Rustã¯ãã¼ã¸ã£ã®å®ç¾©ã¯ç°¡ç´ éãã¦éã«ãããã¥ããã®ã§ãä¸ã¤ãã¤è¦ã¦ãããã
- ã¾ãå¼æ°ã¯
|
ã¨|
ã®éã«æãã§å®ç¾©ãããä¸ã®ä¾ã ã¨ãarg
ãå¼æ°ã§ããã - å¼æ°ãå®ç¾©ããå¾ã«å¼ãå®ç¾©ãããä¸ã®ä¾ã ã¨
arg + 1i32
ãããã§ããã- Rustã§ã¯éä¸å¼ããªãå ´å
{}
ãå¿ è¦ãªãããã¡ããéä¸å¼ããã£ãããæ示çã«å¼ãå²ã£ããããå ´åã¯{}
ã使ãã
- Rustã§ã¯éä¸å¼ããªãå ´å
2.ãããæ示çã«{}
ãå ããããé¢æ°å®ç¾©ãããæ¸ããã®ã以ä¸ã®ã³ã¼ãã§ããã
let closure = |arg| { arg + 1i32 };
ã¾ããRustã¯ãã¼ã¸ã£ãå®ç¾©ããéã«ãå注éããããã¨ãå¯è½ã§ãããå ã»ã©ã®ã³ã¼ãã«å注éãå ãã¦ã¿ãã
let closure = |arg: i32| -> i32 { arg + 1i32 };
ãªããRustã¯ãã¼ã¸ã£ã®å®ç¾©ã¯é¢æ°å®ç¾©ã¨ã¯éãã¸ã§ããªã¯ã¹ãã©ã¤ãã¿ã¤ã 注éã¯ä½¿ç¨ã§ããªãããã ãæ®éãããå¿ è¦ãªç¨éã§ä½¿ããããã¨ã¯ãªãã®ã§ãããã«é¢ãã¦å°ããã¨ã¯ãªãã ããã
æ®éã®é¢æ°å®ç¾©ã¨Rustã¯ãã¼ã¸ã£ã®å®ç¾©ãéãã®ã¯ãRustã¯ãã¼ã¸ã£ã®å¤å´ã®å¤æ°ãåç
§ããããææ権ãé¢æ°å
ã«ç§»åãããã§ããï¼Rustçã«ã¯Rustã¯ãã¼ã¸ã£å
ã«ææ権ã移åããããã¨ããææ権ã奪ããã¨è¨ããããï¼ã¨ããç¹ã§ããã
ãã¨ãã°ã以ä¸ã®ã³ã¼ãã¯Rustã¯ãã¼ã¸ã£ã®å¤å´ã®å¤æ°ãåç
§ãã¦ããã
// æ§é ä½ã®å®ç¾©(çç±ã¯å¾è¿°) #[derive(Debug)] struct Struct(i32); fn main() { let mut s = Struct(0i32); // Structã®ã¤ã³ã¹ã¿ã³ã¹ãä½æ // mutå¤æ°ã¸ã®ç ´å£çä»£å ¥ã®ããRustã¯ãã¼ã¸ã£ã¯mutãå¿ è¦ let mut f = || { s.0 += 1i32; }; // Rustã¯ãã¼ã¸ã£ã®å®è¡ f(); println!("{s:?}"); // => Struct(1) }
注æã¨ãã¦ãmut
å¤æ°ã¸ã®ç ´å£ç代å
¥ã®ããRustã¯ãã¼ã¸ã£ã¯mut
ãå¿
è¦ã¨ããç¹ãããããã ããç ´å£ç代å
¥ããã¦ããªããã°ãã¨ãmut
å¤æ°ã ã¨ãã¦ãRustã¯ãã¼ã¸ã£ãmut
ã§ããå¿
è¦ã¯ãªãã
å
ã»ã©ã®ä¾ã¯å¤æ°ãåç
§ãã¦ããã次ã«ææ権ã奪ã£ã¦ã¿ãã
Rustã¯ãã¼ã¸ã£ã§ææ権ã奪ãã«ã¯ãRustã¯ãã¼ã¸ã£ã®å®ç¾©ã®å
é ã«move
ãä»ããã
#[derive(Debug)] struct Struct(i32); fn main() { let mut s = Struct(0i32); // ææ権ã奪ãããã«ã¯Rustã¯ãã¼ã¸ã£ã®å®ç¾©ã®å é ã«moveãä»ãã let mut f = move || { s.0 += 1i32; println!("{s:?}"); }; // Rustã¯ãã¼ã¸ã£ã®å®è¡ f(); // WARNING: ææ権ã奪ãããã®ã§ãå¤æ°sã¯ãã使ããªã // s; }
Rustçã«ææ権ã奪ã£ãã¨ãããã¨ã¯ã以ä¸ã®ä¾ã§è¨ãã¨ããã®å¤æ°s
ã¯ãã使ããªããã¨ãæå³ããããã®ããææ権ã奪ãããå¾å¤æ°s
ã使ããã¨ããã¨ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªãã
ã¡ãªã¿ã«ããã¯ãææ権ã®ç§»åã¨æå³çã«ã¯åãã§ããããã®ãããå ã»ã©ã®ã³ã¼ãã¯ä»¥ä¸ã®ã³ã¼ãã¨ç価ã§ããã
#[derive(Debug)] struct Struct(i32); fn main() { let s = Struct(0i32); let mut moved_s = s; // ææ権ã®ç§»å // å¦çã®å®è¡ { moved_s.0 += 1i32; println!("{moved_s:?}"); } // WARNING: ææ権ã奪ãããã®ã§ãå¤æ°sã¯ãã使ããªã // s; }
ããããããã¨åç´åãããæ£ç¢ºã«è¨ãã°Copyãã¬ã¤ããå®è£
ããã¦ããåã®å¤æ°ã«ããã¦ãRustã¯ãã¼ã¸ã£ã®move
ã¯å¤æ°ã®ã³ãã¼ã§ãããã¨ããããã ããã
#[allow(path_statements)] fn main() { let mut v = 0i32; // åç´åã«ããã¦moveã¯ãå¤æ°ã®ã³ãã¼ãã§ããã let mut f = move || { v += 1i32; println!("{v}"); }; // Rustã¯ãã¼ã¸ã£ã®å®è¡ f(); // å¤ãã³ãã¼ããã¦ããã®ã§å¤æ°ã使ãã v; }
å ã»ã©ããã¦æ§é ä½ã使ã£ã¦ããã®ã¯ãåç´åã使ãã¨ææ権ã移åããï¼åç´åã«ããã¦ã¯å¤ãã³ãã¼ããï¼ã¨ãããã¨ããããã«ããã£ãããã§ãã*1ã次以éã¯æ®éã«åç´åã使ã£ã¦ããã
以ä¸ãRustã¯ãã¼ã¸ã£ã§ããã
ãããããã¯ãã¼ã¸ã£ãã®å®ç¾©ã¨ã¯ï¼
ããããã¯ãã¼ã¸ã£ã®å®ç¾©ã¯ãå½¢å¼çã«ã¯ãèªç±å¤æ°ãä½ããã®å¦çã«éãè¾¼ãããã®ãã§ããããã®ãä½ããã®å¦çãã¯ãå®ã¯é¢æ°ã§ããå¿
è¦ã¯ãªãï¼ãã ãã»ã¨ãã©ã®å ´åã«ããã¦é¢æ°ã§ããï¼ããã®ããæ§ã
ãªãµã¤ãã§è¦ãããã¯ãã¼ã¸ã£ã®å訳ãé¢æ°éå
ãã¯ããã¾ãæé©ãªè¨³ã¨ã¯è¨ããªãã
ã¤ã¡ã¼ã¸ã¨ãã¦ã¯ã以ä¸ã®ãããªã¤ã¡ã¼ã¸ã§ããã
ããã§éè¦ãªã®ããéãè¾¼ããã®ã¯ãå¤æ°ã®ã³ãã¼ãã§ã¯ãªãããå¤æ°ãã®ãã®ãã§ããã¨ããç¹ã§ãããã¤ã¾ããRustã§ã使ããããç°å¢ããã£ããã£ãããã¨ããã®ã¯å®ã¯ããå¤æ°ãã®ãã®ããä½ããã®å¦çã«éãããã¨ããæå³ã§ãå°ãªãã¨ããå¤æ°ã®åç §ãã§ãªãã¨ã¯ãã¼ã¸ã£ã¨ã¯è¨ããªãããã§ããã
ã§ã¯ã¯ãã¼ã¸ã£ãå®éã«ã©ã®ããã«åããã®ãªã®ã確èªãã¦ãããã
ãã¯ãã¼ã¸ã£ã¨è¨ãã°ãã§åºã¦ããã®ãJavaScriptã§ããããã®JavaScriptã¯æ£çæ£éã®ã¯ãã¼ã¸ã£ããµãã¼ããã¦ããã
æ©éãã®ä¾ãè¦ã¦ã¿ãããECMAScript 2015以éããµãã¼ããã¦ãããã©ã¦ã¶ã§ããã¨ãã*2ã
/** * ã¯ãã¼ã¸ã£ãä½ãé¢æ°ãxã¯èªç±å¤æ°ã */ function createClosure(x) { const xView = () => console.log(`x = ${x}`); // xããã°åºåããã¯ãã¼ã¸ã£ const xUpdate = () => ++x; // xã+1ããã¯ãã¼ã¸ã£ // (1) ã¾ãã¯xããã°åºå xView(); // (2) xãæ´æ°ãã¦ãããã°åºå xUpdate(); // xãæ´æ° xView(); // xããã°åºå // (3) xUpdateãæ»ãå¤ã¨ãã¦è¿ã return xUpdate; } // ã¯ãã¼ã¸ã£ãçæãã const closure = createClosure(0); // (4) ã¯ãã¼ã¸ã£ãå®è¡ãã¦ã¿ã console.log(`closure() = ${closure()}`);
ã³ã¡ã³ãã§(1)ï½(4)ã¾ã§ãã³ããªã³ã°ããã®ã§é çªã«å¦çã追ã£ã¦ã¿ããã
- (1) ã¾ãã¯xããã°åºå
// (1) ã¾ãã¯xããã°åºå
xView();
ã¯ãã¼ã¸ã£ãçæããéã«ãã¾ããã®å¦çãå®è¡ããããããã¦ãã°ã«ã¯ä»¥ä¸ã®ããã«è¡¨ç¤ºãããã¯ãã§ããã
x = 0
çæã®éã«ã¯å¼æ°ã«0ã渡ãã¦ããã®ã§ããã¯æ£ããçµæã§ããã
- (2) xãæ´æ°ãã¦ãããã°åºå
// (2) xãæ´æ°ãã¦ãããã°åºå xUpdate(); // xãæ´æ° xView(); // xããã°åºå
次ã«ãxUpdate()
ã§x
ã+1
ããããã®å¾ã«ããä¸åº¦xView()
ã§ãã°åºåããã¨ã以ä¸ã®ããã«è¡¨ç¤ºãããã¯ãã§ããã
x = 1
ãã®ãã¨ãããåã¯ãã¼ã¸ã£ã¯ãå¤æ°ãã³ãã¼ãã¦ãããã®ã§ã¯ãªãããå¤æ°ãåç §ãã¦ããããã¨ããããã
- (3) xUpdateãæ»ãå¤ã¨ãã¦è¿ã
// (3) xUpdateãæ»ãå¤ã¨ãã¦è¿ã return xUpdate;
æåéããxUpdate
ãæ»ãå¤ã¨ãã¦è¿ãã¦ãããã¤ã¾ãã以ä¸ã®ä»£å
¥ã§ã¯ãclosure
ã«xUpdate
ã代å
¥ããããã¨ããããã
// ã¯ãã¼ã¸ã£ãçæãã const closure = createClosure(0);
- (4) ã¯ãã¼ã¸ã£ãå®è¡ãã¦ã¿ã
// (4) ã¯ãã¼ã¸ã£ãå®è¡ãã¦ã¿ã console.log(`closure() = ${closure()}`);
æå¾ã«ã¯ãã¼ã¸ã£ãå®è¡ããããããã°åºåãããããã¨ã以ä¸ã®ããã«è¡¨ç¤ºãããã
closure() = 2
ããã¯ã¨ã¦ãä¸æè°ãªçµæã§ããããªããªãã°ãèªç±å¤æ°x
ã¯createClosure()
ãçµäºããæç¹ã§ã¡ã¢ãªè§£æ¾ããã¦ããã¯ãã ããã ããããç¾ã«ã¡ããã¨è¡¨ç¤ºããã¦ããã
ããã¯ãã³ã°ãªã³ã°ãã¤ã³ã¿*3ã«ãã£ã¦å¼ãèµ·ãããæªå®ç¾©åä½*4ãªã®ã§ã¯æ±ºãã¦ãªãããã¡ãã¨è¨èªä»æ§ä¸ã§å®ç¾©ããã¦ããåä½ã§ããã
ã¤ã¾ãJavaScriptã®å¦çç³»ã¯ã¯ãã¼ã¸ã£ãçæããéã«èªç±å¤æ°ã解æ¾ããªãããã«å¦çãã¦ãããã®ã§ããã
ãããããæ£çæ£éã®ã¯ãã¼ã¸ã£ã¨ãã¦ã®è½åã§ããã以ä¸ãããã¯ãã¼ã¸ã£ã«ã¯ããå¤æ°ãã®ãã®ããéãè¾¼ãããæ©è½ãå¿ è¦ã§ããã¨ãããã¨ãããã£ãã®ã§ã¯ãªãã ãããã
ãªãRustã®ã¯ãã¼ã¸ã£ã¯ãã¯ãã¼ã¸ã£ãã§ã¯ãªãã®ãï¼
Rustã¯ãã¼ã¸ã£ã§ã¯ãç°å¢ããã£ããã£ãããéãmove
ãä»ãã¦ããªããã°èªç±å¤æ°ãåç
§ãã¦ãããããã¾ã§ã¯è¯ããã ãããããã£ãRustã¯ãã¼ã¸ã£ãæ»ãå¤ã¨ãã¦è¿ãã¨ãããåé¡ãçºçãããæ©éè¦ã¦è¦ããã
/// Rustã¯ãã¼ã¸ã£ã®çæãxã¯èªç±å¤æ°ã /// /// note: Rustã¯ãã¼ã¸ã£ãè¿ãã¨ãæ»ãå¤ã®åãimpl Fn*ã«ãã /// ãã¥ã¼ã¿ãã«ãªRustã¯ãã¼ã¸ã£ãè¿ãå ´åã¯impl FnMutãè¿ã fn create_closure(mut x: i32) -> impl FnMut() -> i32 { || { x += 1i32; x } }
ããã¯ã³ã³ãã¤ã«ã¨ã©ã¼ã«ãªãã
error[E0597]: `x` does not live long enough --> ... | xx | || { | -- value captured here xx | x += 1i32; | ^ borrowed value does not live long enough ... xx | } | - | | | `x` dropped here while still borrowed | borrow later used here For more information about this error, try `rustc --explain E0597`.
ãªããã¨ããã¨ãèªç±å¤æ°x
ã¯é¢æ°create_closure()
çµäºæç¹ã§è§£æ¾ãããã®ã«ãé¢ããããæ»ãå¤ã¨ãªãRustã¯ãã¼ã¸ã£ã§åç
§ãã¦ä½¿ããã¨ãã¦ããããã§ããã
ããã解決ãããããã«ã¯ãRustã¯ãã¼ã¸ã£ã®å®ç¾©ã«move
ãä»ããã
/// Rustã¯ãã¼ã¸ã£ã®çæãxã¯èªç±å¤æ°ã fn create_closure(mut x: i32) -> impl FnMut() -> i32 { move || { x += 1i32; x } } fn main() { let mut closure = create_closure(0i32); // Rustã¯ãã¼ã¸ã£ãçæ // Rustã¯ãã¼ã¸ã£ãå®è¡ãã¦æ¨æºåºåãã println!("closure() = {}", closure()); }
ãããå
ã»ã©ãæ¸ããã¨æãããmove
ã¯ææ権ã®ç§»åã¾ãã¯ã³ãã¼ããããã¨ã示ãã¦ãã¦ã決ãã¦ãå¤æ°ãã®ãã®ããéãè¾¼ãã¦ããããã§ã¯ãªããã¤ã¾ãããã¯ã¯ãã¼ã¸ã£ãå©ç¨ãã¦ä½ã£ãã®ã§ã¯ãªãã
以ä¸ã®ã³ã¼ããå®è¡ãã¦ã¿ã¦ããããããããã ããã
/// Rustã¯ãã¼ã¸ã£ã®çæãxã¯èªç±å¤æ°ã fn create_closure(mut x: i32) -> impl FnMut() -> i32 { // xãæ¨æºåºåããRustã¯ãã¼ã¸ã£ let x_view = move || { println!("x = {x}"); }; // xã+1ããRustã¯ãã¼ã¸ã£ let mut x_update = move || { x += 1i32; x }; // (1) ã¾ãã¯æ¨æºåºå x_view(); // (2) xãæ´æ°ãã¦ããæ¨æºåºå x_update(); // xãæ´æ° x_view(); // xãæ¨æºåºå // (3) x_updateãæ»ãå¤ã¨ãã¦è¿ã x_update } fn main() { let mut closure = create_closure(0i32); // Rustã¯ãã¼ã¸ã£ãçæ // (4) Rustã¯ãã¼ã¸ã£ãå®è¡ãã¦ã¿ã println!("closure() = {}", closure()); }
以ä¸ãããRustã®ã¯ãã¼ã¸ã£ã¯å³å¯ã«ã¯ã¯ãã¼ã¸ã£ã§ã¯ãªããã¨ããããã
Rustã®ã¯ãã¼ã¸ã£ã§çä¼¼çãªã¯ãã¼ã¸ã£ãä½ã
Rustã¯ãã¼ã¸ã£ã¯ã¯ãã¼ã¸ã£ã§ã¯ãªãã¨ãããã¨ã§ãç°¡åã«ã¯Rustã§ã¯ãã¼ã¸ã£ãä½ããªããã¨ãããã£ããããããRustã¯ãã¼ã¸ã£ã§ã¯ãã¼ã¸ã£ãä½ãããã»ã»ã»ãã¨ãã人ãããã ããã¨æãã®ã§ããã¾ãã¨ãã¦Rustã¯ãã¼ã¸ã£ã§çä¼¼çãªã¯ãã¼ã¸ã£ãä½ã£ã¦ã¿ãã
ã¾ãRustã¯ææ権ã·ã¹ãã ã®é½åä¸ã2ã¤ä»¥ä¸ã®å¤æ°ãåãã¡ã¢ãªã«å¯¾ãã¦mut
ãªæä½ãè¡ã£ã¦ã¯ãªããªãããã®ããå¤æ°ã¨ãã®åç
§ããåæã«æ¸ãè¾¼ãã¨è¨ã£ãæä½ãã§ããªãã
#[allow(unused_assignments)] fn main() { let mut x = 0i32; let ref_x = &mut x; *ref_x += 1i32; x += 1i32; // WARNING: ref_xã¯ãã使ããªã // *ref_x += 1i32; }
ã ã幸ããªãã¨ã«Rustã§ã¯mut
å¤æ°ã§ãªãã¦ãå¤æ°å
é¨ã§å¯å¤æ§ãæããããã¨ãå¯è½ã ããããå
é¨å¯å¤æ§ã¨è¨ãã
Rustã®å¤æ°ãå
é¨çã«å¯å¤ã«ããããã«ã¯ãstd::cell::Cell
ãããã¯std::cell::RefCell
ã使ãããã®2ã¤ã«ã¤ãã¦ã®è©³ç´°ã¯çããã以ä¸ã®ããã«ä½¿ãåããã¨è¯ãã ããã
- åã«
Copy
ãã¬ã¤ããå®è£ ããã¦ãã
ã=>std::cell::Cell
- åã«
Copy
ãã¬ã¤ããå®è£ ããã¦ããªã
ã=>std::cell::RefCell
ã§ã¯ä»¥ä¸ã®ç¥èããã¨ã«ã以ä¸ã®2ã¤ã®å®è£ ãè¦ã¦ãããã
(1) ãã¼ãã¡ã¢ãªã使ããªãå®è£
(2)ã§ã¯ãã¼ãã¡ã¢ãªã使ãã®ã ãããã®éã«ããä¸ã¤ç¥èãå¿ è¦ã¨ãªãã®ã§ãã¾ãã¯ãã®ç¥èãå¿ è¦ãªããã¼ãã¡ã¢ãªã使ããªãå®è£ ããè¦ã¦ãããã
std::cell::Cell
ã使ã£ãå®è£
use std::cell::Cell; /// Rustã¯ãã¼ã¸ã£ã®çæãxã¯èªç±å¤æ°ã fn create_closure(x: Cell<i32>) -> impl FnMut() -> i32 { // xãæ¨æºåºåããRustã¯ãã¼ã¸ã£ let x_view = || { println!("x = {}", x.get()); }; // xã+1ããRustã¯ãã¼ã¸ã£ let x_update = || { x.set(x.get() + 1i32); x.get() }; // ã¾ãã¯æ¨æºåºå x_view(); // xãæ´æ°ãã¦ããæ¨æºåºå x_update(); // xãæ´æ° x_view(); // xãæ¨æºåºå // x_updateã¯æ»ãå¤ã¨ãã¦è¿ããªãã®ã§ãCellãæ¶è²»ã㦠// æ°ããmoveãä»ãã¦å®ç¾©ããRustã¯ãã¼ã¸ã£ãè¿ã let mut x = x.into_inner(); move || { x += 1i32; x } } fn main() { let mut closure = create_closure(Cell::new(0i32)); // Rustã¯ãã¼ã¸ã£ãçæ // Rustã¯ãã¼ã¸ã£ãå®è¡ãã¦ã¿ã println!("closure() = {}", closure()); }
std::cell::RefCell
ã使ã£ãå®è£
use std::cell::RefCell; #[derive(Debug, Clone)] struct Struct(i32); /// Rustã¯ãã¼ã¸ã£ã®çæãsã¯èªç±å¤æ°ã fn create_closure(s: RefCell<Struct>) -> impl FnMut() -> Struct { // sãæ¨æºåºåããRustã¯ãã¼ã¸ã£ let s_view = || { println!("s = {:?}", s.borrow()); }; // s.0ã+1ããRustã¯ãã¼ã¸ã£ let s_update = || { s.borrow_mut().0 += 1i32; <Struct as Clone>::clone(&s.borrow()) }; // ã¾ãã¯æ¨æºåºå s_view(); // sãæ´æ°ãã¦ããæ¨æºåºå s_update(); // sãæ´æ° s_view(); // sãæ¨æºåºå // s_updateã¯æ»ãå¤ã¨ãã¦è¿ããªãã®ã§ãCellãæ¶è²»ã㦠// æ°ããmoveãä»ãã¦å®ç¾©ããRustã¯ãã¼ã¸ã£ãè¿ã let mut s = s.into_inner(); move || { s.0 += 1i32; <Struct as Clone>::clone(&s) } } fn main() { // Rustã¯ãã¼ã¸ã£ãçæ let mut closure = create_closure(RefCell::new(Struct(0i32))); // Rustã¯ãã¼ã¸ã£ãå®è¡ãã¦ã¿ã println!("closure() = {:?}", closure()); }
ãã®å®è£
ã§ã¯é¢æ°å
é¨ã®Rustã¯ãã¼ã¸ã£ã§ã¯ä¸å¤åç
§ãã¦ããã¦ãæ»ãå¤ã¨ãã¦è¿ãã¨ãã«ãæ°ããRustã¯ãã¼ã¸ã£ãè¿ãã¦ãããããã«ãããããããã¯ãã¼ã¸ã£ãå©ç¨ãããã®ãããªå®è£
ãå¯è½ã ã
ããããã¼ãã¡ã¢ãªã使ããªããããåä½ãé«éã§ãçµè¾¼ã¿ç°å¢ã§ã使ãããããããªã*5*6ã
(2) ãã¼ãã¡ã¢ãªã使ã£ãå®è£
Rustã®æ¨æºã¯ã¬ã¼ãã«ããstd::rc::Rc
ã使ããã¨ã§ããããã¯ãã¼ã¸ã£ããããå®è£
ãå¯è½ã¨ãªãããã ããstd::rc::Rc
ã¯å
é¨ã§ãã¼ãã¡ã¢ãªã使ããããããªå®è£
ãããã¦ãããåºæ¬çã«(1)ããã¯ä½éã¨ãªãã
std::cell::Cell
ã使ã£ãå®è£
use std::{ cell::Cell, rc::Rc }; /// Rustã¯ãã¼ã¸ã£ã®çæãxã¯èªç±å¤æ°ã /// /// note: æ»ãå¤ã®åã¯impl Fnã§ãè¯ãããæ··ä¹±ãé¿ããããimpl FnMutã¨ãã fn create_closure(x: Rc<Cell<i32>>) -> impl FnMut() -> i32 { let x_clone = Rc::clone(&x); // ææ権ãè¤è£½ãã // xãæ¨æºåºåããRustã¯ãã¼ã¸ã£ let x_view = move || { println!("x = {}", x.get()); }; // xã+1ããRustã¯ãã¼ã¸ã£ let x_update = move || { x_clone.set(x_clone.get() + 1i32); x_clone.get() }; // ã¾ãã¯æ¨æºåºå x_view(); // xãæ´æ°ãã¦ããæ¨æºåºå x_update(); // xãæ´æ° x_view(); // xãæ¨æºåºå // ãã¼ãã¡ã¢ãªã®å ´åã¯èªåã§ã¡ã¢ãªã解æ¾ããããã§ã¯ãªãã®ã§ // x_updateãæ»ãå¤ã¨ãã¦è¿ãã x_update } fn main() { // Rustã¯ãã¼ã¸ã£ãçæ let mut closure = create_closure(Rc::new(Cell::new(0i32))); // Rustã¯ãã¼ã¸ã£ãå®è¡ãã¦ã¿ã println!("closure() = {}", closure()); }
std::cell::RefCell
ã使ã£ãå®è£
use std::{ cell::RefCell, rc::Rc }; #[derive(Debug, Clone)] struct Struct(i32); /// Rustã¯ãã¼ã¸ã£ã®çæãxã¯èªç±å¤æ°ã fn create_closure(s: Rc<RefCell<Struct>>) -> impl FnMut() -> Struct { let s_clone = Rc::clone(&s); // ææ権ãè¤è£½ãã // sãæ¨æºåºåããRustã¯ãã¼ã¸ã£ let s_view = move || { println!("s = {:?}", s.borrow()); }; // s.0ã+1ããRustã¯ãã¼ã¸ã£ let s_update = move || { s_clone.borrow_mut().0 += 1i32; <Struct as Clone>::clone(&s_clone.borrow()) }; // ã¾ãã¯æ¨æºåºå s_view(); // sãæ´æ°ãã¦ããæ¨æºåºå s_update(); // sãæ´æ° s_view(); // sãæ¨æºåºå // ãã¼ãã¡ã¢ãªã®å ´åã¯èªåã§ã¡ã¢ãªã解æ¾ããããã§ã¯ãªãã®ã§ // s_updateãæ»ãå¤ã¨ãã¦è¿ãã s_update } fn main() { // Rustã¯ãã¼ã¸ã£ãçæ let mut closure = create_closure(Rc::new(RefCell::new(Struct(0i32)))); // Rustã¯ãã¼ã¸ã£ãå®è¡ãã¦ã¿ã println!("closure() = {:?}", closure()); }
*1:ãããã³ã¼ãã§ã¯"move"ã¨æ¸ãã¦ããã®ã«å®éã«ãã£ã¦ããã®ã¯å¤ã®ã³ãã¼ã¨ãããã«ãããã¨ãã®ä¸ãªãã»ã»ã»
*2:è¦ãããã®ãããECMAScript 5以åã§ãåæ§ã®å¦çãæ¸ããã¨ãå¯è½ã§ãã
*3:ã¡ã¢ãªã解æ¾ããã¦ãã¦ããã¤åç §ã§ãã¦ãã¾ãå¤æ°ã®ãã¤ã³ã¿
*4:å¦çç³»ã«ãã£ã¦åä½ãå¤ãã£ã¦ãã¾ããã¨ãæå³ãããä½ãèµ·ããã®ãããããªããããåºæ¬æªå®ç¾©åä½ãããããªã³ã¼ãã¯æ¸ãã¹ãã§ã¯ãªã
*5:çµè¾¼ã¿ç°å¢ã®å ´åã¯core::cell::Cellãããã¯core::cell::RefCellã使ããã¨ã«ãªã
*6:ã¾ãçµè¾¼ã¿ç°å¢ãªãããããçãã¤ã³ã¿ãcore::cell::UnsafeCellã使ããã¨ã«ãªãã®ãããããªãã