fn make_adder(x: String) -> Box<Fn() -> String> {
Box::new(|| x)
}
fn main() {
make_adder(String::from("a"));
}
这会导致此错误:
error[E0507]: cannot move out of captured outer variable in an `Fn` closure
--> src/main.rs:2:17
|
1 | fn make_adder(x: String) -> Box<Fn() -> String> {
| - captured outer variable
2 | Box::new(|| x)
| ^ cannot move out of captured outer variable in an `Fn` closure
如何使其正确?
答案 0 :(得分:2)
实现Fn
的闭包可以被多次调用(接收器参数是public string Decrypt(string cipherText)
{
string EncryptionKey = "myPassword";
cipherText = cipherText.Replace(" ", "+");
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] {
0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.Padding = PaddingMode.None;
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return cipherText;
}
,是对闭包的不可变引用):
&self
这意味着关闭fn call_multiple_times<F: Fn(u8) -> i32>(f: F) {
// Works! We can call the closure mutliple times
let a = f(1);
let b = f(27);
let c = f(31);
}
,你可以这样做:
Fn() -> String
现在你有两个let s1 = adder();
let s2 = adder();
s虽然你只开始一个!魔术?你当然可以通过克隆原始字符串获得另一个字符串,但我们不会在这里做。所以它显然无法运作。
您可以通过两种方式解决这个问题。要么你不需要多次调用你的闭包。在这种情况下,您只需将String
更改为FnOnce
(要求不高的特质)。只能调用Fn
闭包......好吧......一次。这有效:
FnOnce
另一方面,也许您希望多次调用闭包并始终希望返回字符串的新克隆。你可以这样做:
fn make_adder(x: String) -> Box<FnOnce() -> String> {
Box::new(|| x)
}
这里我们添加了fn make_adder(x: String) -> Box<Fn() -> String> {
Box::new(move || x.clone())
}
调用(因为在Rust中,深层克隆从不隐含!)我们添加了.clone()
关键字。后者是明确将字符串move
移动到闭包中所必需的,而不仅仅是借用它。