Why cant a static hashmap for a memoizing function be borrowed as mutable?
I'm trying to create a memoization function in Rust
. The problem comes when getting a mutable reference for the cache HashMap
. I'm not still confident with the type system and I'm struggling a bit.
use std::collections::HashMap;
use std::hash::Hash;
fn memoize<A, B, F>(f: F, cache: &'static HashMap<A, B>) -> impl Fn(A) -> B
where
A: Eq + Hash + Copy,
B: Clone,
F: Fn(A) -> B,
if !cache.contains_key(&value)
cache.insert(value, f(value.clone()));
let res = cache.get(&value).unwrap();
res.clone()
The error is:
error[E0596]: cannot borrow immutable borrowed content `**cache` as mutable
--> src/lib.rs:12:13
|
12 | cache.insert(value, f(value.clone()));
| ^^^^^ cannot borrow as mutable
Why cannot a static lifetime parameter be mutable?
static rust lifetime mutable
add a comment |
I'm trying to create a memoization function in Rust
. The problem comes when getting a mutable reference for the cache HashMap
. I'm not still confident with the type system and I'm struggling a bit.
use std::collections::HashMap;
use std::hash::Hash;
fn memoize<A, B, F>(f: F, cache: &'static HashMap<A, B>) -> impl Fn(A) -> B
where
A: Eq + Hash + Copy,
B: Clone,
F: Fn(A) -> B,
if !cache.contains_key(&value)
cache.insert(value, f(value.clone()));
let res = cache.get(&value).unwrap();
res.clone()
The error is:
error[E0596]: cannot borrow immutable borrowed content `**cache` as mutable
--> src/lib.rs:12:13
|
12 | cache.insert(value, f(value.clone()));
| ^^^^^ cannot borrow as mutable
Why cannot a static lifetime parameter be mutable?
static rust lifetime mutable
add a comment |
I'm trying to create a memoization function in Rust
. The problem comes when getting a mutable reference for the cache HashMap
. I'm not still confident with the type system and I'm struggling a bit.
use std::collections::HashMap;
use std::hash::Hash;
fn memoize<A, B, F>(f: F, cache: &'static HashMap<A, B>) -> impl Fn(A) -> B
where
A: Eq + Hash + Copy,
B: Clone,
F: Fn(A) -> B,
if !cache.contains_key(&value)
cache.insert(value, f(value.clone()));
let res = cache.get(&value).unwrap();
res.clone()
The error is:
error[E0596]: cannot borrow immutable borrowed content `**cache` as mutable
--> src/lib.rs:12:13
|
12 | cache.insert(value, f(value.clone()));
| ^^^^^ cannot borrow as mutable
Why cannot a static lifetime parameter be mutable?
static rust lifetime mutable
I'm trying to create a memoization function in Rust
. The problem comes when getting a mutable reference for the cache HashMap
. I'm not still confident with the type system and I'm struggling a bit.
use std::collections::HashMap;
use std::hash::Hash;
fn memoize<A, B, F>(f: F, cache: &'static HashMap<A, B>) -> impl Fn(A) -> B
where
A: Eq + Hash + Copy,
B: Clone,
F: Fn(A) -> B,
if !cache.contains_key(&value)
cache.insert(value, f(value.clone()));
let res = cache.get(&value).unwrap();
res.clone()
The error is:
error[E0596]: cannot borrow immutable borrowed content `**cache` as mutable
--> src/lib.rs:12:13
|
12 | cache.insert(value, f(value.clone()));
| ^^^^^ cannot borrow as mutable
Why cannot a static lifetime parameter be mutable?
static rust lifetime mutable
static rust lifetime mutable
edited Nov 15 '18 at 15:33
Shepmaster
157k14316457
157k14316457
asked Nov 14 '18 at 9:44
NetwaveNetwave
12.7k22145
12.7k22145
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
A variable is immutable by default in Rust, therefore you cannot mutate a variable that is not declared as mut
. The 'static
lifetime does not influence the mutability, but only how long the variable lives.
A Fn
"[...] can be called repeatedly without mutating state.". And exactly here is the problem. You want to mutate the environment (in this case your HashMap
).
You have to use a FnMut
to be able to mutate the environment.
If you use the Entry API, you can simplify your code:
use std::collections::HashMap;
use std::hash::Hash;
fn memoize<A, B, F>(f: F, cache: &'static mut HashMap<A, B>) -> impl FnMut(A) -> B
where
A: Eq + Hash + Copy,
B: Clone,
F: Fn(A) -> B,
let res = cache.entry(value).or_insert_with(
As a sidenote, if you compile your code with #[feature(nll)]
the error message is actually very good.
error[E0596]: cannot borrow `*cache` as mutable, as `Fn` closures cannot mutate their captured variables
--> src/lib.rs:14:13
|
14 | cache.insert(value, f(value.clone()));
| ^^^^^ cannot borrow as mutable
|
help: consider changing this to accept closures that implement `FnMut`
Well, I was pretty close to it. I actually tried themut
modifyer after the static, but even if I read about theFnMut
I forgot to use it! Thanks!!
– Netwave
Nov 14 '18 at 9:57
1
@Netwave I optimized the code a litte bit 😸. Of course you can omitres
as such and just write.clone()
at the end of the first closure line:cache.entry(value).or_insert_with(|| f(value)).clone()
– hellow
Nov 14 '18 at 10:23
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297128%2fwhy-cant-a-static-hashmap-for-a-memoizing-function-be-borrowed-as-mutable%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
A variable is immutable by default in Rust, therefore you cannot mutate a variable that is not declared as mut
. The 'static
lifetime does not influence the mutability, but only how long the variable lives.
A Fn
"[...] can be called repeatedly without mutating state.". And exactly here is the problem. You want to mutate the environment (in this case your HashMap
).
You have to use a FnMut
to be able to mutate the environment.
If you use the Entry API, you can simplify your code:
use std::collections::HashMap;
use std::hash::Hash;
fn memoize<A, B, F>(f: F, cache: &'static mut HashMap<A, B>) -> impl FnMut(A) -> B
where
A: Eq + Hash + Copy,
B: Clone,
F: Fn(A) -> B,
let res = cache.entry(value).or_insert_with(
As a sidenote, if you compile your code with #[feature(nll)]
the error message is actually very good.
error[E0596]: cannot borrow `*cache` as mutable, as `Fn` closures cannot mutate their captured variables
--> src/lib.rs:14:13
|
14 | cache.insert(value, f(value.clone()));
| ^^^^^ cannot borrow as mutable
|
help: consider changing this to accept closures that implement `FnMut`
Well, I was pretty close to it. I actually tried themut
modifyer after the static, but even if I read about theFnMut
I forgot to use it! Thanks!!
– Netwave
Nov 14 '18 at 9:57
1
@Netwave I optimized the code a litte bit 😸. Of course you can omitres
as such and just write.clone()
at the end of the first closure line:cache.entry(value).or_insert_with(|| f(value)).clone()
– hellow
Nov 14 '18 at 10:23
add a comment |
A variable is immutable by default in Rust, therefore you cannot mutate a variable that is not declared as mut
. The 'static
lifetime does not influence the mutability, but only how long the variable lives.
A Fn
"[...] can be called repeatedly without mutating state.". And exactly here is the problem. You want to mutate the environment (in this case your HashMap
).
You have to use a FnMut
to be able to mutate the environment.
If you use the Entry API, you can simplify your code:
use std::collections::HashMap;
use std::hash::Hash;
fn memoize<A, B, F>(f: F, cache: &'static mut HashMap<A, B>) -> impl FnMut(A) -> B
where
A: Eq + Hash + Copy,
B: Clone,
F: Fn(A) -> B,
let res = cache.entry(value).or_insert_with(
As a sidenote, if you compile your code with #[feature(nll)]
the error message is actually very good.
error[E0596]: cannot borrow `*cache` as mutable, as `Fn` closures cannot mutate their captured variables
--> src/lib.rs:14:13
|
14 | cache.insert(value, f(value.clone()));
| ^^^^^ cannot borrow as mutable
|
help: consider changing this to accept closures that implement `FnMut`
Well, I was pretty close to it. I actually tried themut
modifyer after the static, but even if I read about theFnMut
I forgot to use it! Thanks!!
– Netwave
Nov 14 '18 at 9:57
1
@Netwave I optimized the code a litte bit 😸. Of course you can omitres
as such and just write.clone()
at the end of the first closure line:cache.entry(value).or_insert_with(|| f(value)).clone()
– hellow
Nov 14 '18 at 10:23
add a comment |
A variable is immutable by default in Rust, therefore you cannot mutate a variable that is not declared as mut
. The 'static
lifetime does not influence the mutability, but only how long the variable lives.
A Fn
"[...] can be called repeatedly without mutating state.". And exactly here is the problem. You want to mutate the environment (in this case your HashMap
).
You have to use a FnMut
to be able to mutate the environment.
If you use the Entry API, you can simplify your code:
use std::collections::HashMap;
use std::hash::Hash;
fn memoize<A, B, F>(f: F, cache: &'static mut HashMap<A, B>) -> impl FnMut(A) -> B
where
A: Eq + Hash + Copy,
B: Clone,
F: Fn(A) -> B,
let res = cache.entry(value).or_insert_with(
As a sidenote, if you compile your code with #[feature(nll)]
the error message is actually very good.
error[E0596]: cannot borrow `*cache` as mutable, as `Fn` closures cannot mutate their captured variables
--> src/lib.rs:14:13
|
14 | cache.insert(value, f(value.clone()));
| ^^^^^ cannot borrow as mutable
|
help: consider changing this to accept closures that implement `FnMut`
A variable is immutable by default in Rust, therefore you cannot mutate a variable that is not declared as mut
. The 'static
lifetime does not influence the mutability, but only how long the variable lives.
A Fn
"[...] can be called repeatedly without mutating state.". And exactly here is the problem. You want to mutate the environment (in this case your HashMap
).
You have to use a FnMut
to be able to mutate the environment.
If you use the Entry API, you can simplify your code:
use std::collections::HashMap;
use std::hash::Hash;
fn memoize<A, B, F>(f: F, cache: &'static mut HashMap<A, B>) -> impl FnMut(A) -> B
where
A: Eq + Hash + Copy,
B: Clone,
F: Fn(A) -> B,
let res = cache.entry(value).or_insert_with(
As a sidenote, if you compile your code with #[feature(nll)]
the error message is actually very good.
error[E0596]: cannot borrow `*cache` as mutable, as `Fn` closures cannot mutate their captured variables
--> src/lib.rs:14:13
|
14 | cache.insert(value, f(value.clone()));
| ^^^^^ cannot borrow as mutable
|
help: consider changing this to accept closures that implement `FnMut`
edited Nov 15 '18 at 15:31
Shepmaster
157k14316457
157k14316457
answered Nov 14 '18 at 9:55
hellowhellow
5,33242242
5,33242242
Well, I was pretty close to it. I actually tried themut
modifyer after the static, but even if I read about theFnMut
I forgot to use it! Thanks!!
– Netwave
Nov 14 '18 at 9:57
1
@Netwave I optimized the code a litte bit 😸. Of course you can omitres
as such and just write.clone()
at the end of the first closure line:cache.entry(value).or_insert_with(|| f(value)).clone()
– hellow
Nov 14 '18 at 10:23
add a comment |
Well, I was pretty close to it. I actually tried themut
modifyer after the static, but even if I read about theFnMut
I forgot to use it! Thanks!!
– Netwave
Nov 14 '18 at 9:57
1
@Netwave I optimized the code a litte bit 😸. Of course you can omitres
as such and just write.clone()
at the end of the first closure line:cache.entry(value).or_insert_with(|| f(value)).clone()
– hellow
Nov 14 '18 at 10:23
Well, I was pretty close to it. I actually tried the
mut
modifyer after the static, but even if I read about the FnMut
I forgot to use it! Thanks!!– Netwave
Nov 14 '18 at 9:57
Well, I was pretty close to it. I actually tried the
mut
modifyer after the static, but even if I read about the FnMut
I forgot to use it! Thanks!!– Netwave
Nov 14 '18 at 9:57
1
1
@Netwave I optimized the code a litte bit 😸. Of course you can omit
res
as such and just write .clone()
at the end of the first closure line: cache.entry(value).or_insert_with(|| f(value)).clone()
– hellow
Nov 14 '18 at 10:23
@Netwave I optimized the code a litte bit 😸. Of course you can omit
res
as such and just write .clone()
at the end of the first closure line: cache.entry(value).or_insert_with(|| f(value)).clone()
– hellow
Nov 14 '18 at 10:23
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297128%2fwhy-cant-a-static-hashmap-for-a-memoizing-function-be-borrowed-as-mutable%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown