let say_hello = || println!("hello");
How can I display the address of the closure?
You can use a raw pointer conversion:
fn main() {
let say_hello = || println!("hello");
let address = (&say_hello as *const _) as usize;
println!("{address}");
}
Playground
Also using std::ptr::addr_of and casting again:
let same_address = std::ptr::addr_of!(say_hello) as usize;
Playground
The answer to this question really depends on whether you mean the closure object itself, or the closure's call function.
For example, in this case, the closure captures a variable:
let mut foo = 0;
let mut bar = || foo += 1;
And hence, bar must carry within it a &mut foo.
Therefore, the address of the actual code which is run is different from the address of the closure object.
To concrete this distinction, examine this example:
fn foo() {}
let bar = foo; // `bar` itself is the address of the code for foo.
println!("{:?}", bar as usize); // Prints the address of the code of foo.
println!("{:?}", &bar as *const _ as usize); // Prints the address of `bar`
The second line is essentially what #Netwave's answer does above.
If you are instead looking for the first case, then this isnt necessarily always possible.
If your closure captures items, then it can't be converted to an address of the code in stable rust, since this'd require you have access to it's implementation of FnOnce/Fn/FnMut. However, if you're ok with unstable rust, here's how you'd do it:
#![feature(unboxed_closures, fn_traits)]
fn main() {
let mut x = 0;
let mut foo = || x += 1;
print_addr(foo);
}
fn print_addr<F: FnMut()>(_: F) {
println!("{:?}", <F as std::ops::FnMut<()>>::call_mut as usize);
}
If your closure doesn't capture anything, then the correct way to get the address is to cast it to a function pointer and then cast that to a number:
fn main() {
let foo = || println!("Abc");
println!("{:?}", foo as fn() as usize);
}
Related
I'm new to rust, and am wondering why the following code doesn't result in a:
cannot borrow val as mutable more than once at a time error. It seems like by the time I've reached the second_layer function, I should have three separate references to the same original val variable:
val_ref in the main function body
val_ref2 in the first_layer function body
val_ref3 in the second_layer function body
Any help would be appreciated!
fn first_layer(val_ref2: &mut String)
{
*val_ref2 = String::from("first_layer");
println!("{}", val_ref2);
second_layer(val_ref2);
}
fn second_layer(val_ref3: &mut String)
{
*val_ref3 = String::from("second_layer");
println!("{}", val_ref3);
}
fn main()
{
let mut val = String::from("asdf");
let val_ref: &mut String = &mut val;
first_layer(val_ref);
println!("{}", val_ref);
}
Thanks,
References in a function calling another function temporarily do not exist for the duration of the function call.
Identifiers do not automatically live on in functions called further down the stack. Just because one function calls another does not mean that the callee should have access to the caller's local variables. You would get a not found in this scope if you tried.
What you can (try to) do is create a closure to capture the caller's environment and then reuse one of the caller's variables. But you will find that the compiler complains if you break the borrowing rules.
fn first_layer(val_ref2: &mut String) {
// println!("{}", val); // Cannot use val from main!
*val_ref2 = String::from("first_layer");
println!("{}", val_ref2);
(|val_ref3: &mut String| {
*val_ref3 = String::from("second_layer");
println!("{}", val_ref3);
println!("{}", val_ref2); // This is not allowed
})(val_ref2);
}
fn main() {
let mut val = String::from("asdf");
let val_ref: &mut String = &mut val;
first_layer(val_ref);
println!("{}", val_ref);
}
Another way to think about it is with inlining. If you inline your function second_layer into first_layer you get:
fn first_layer(val_ref2: &mut String)
{
*val_ref2 = String::from("first_layer");
println!("{}", val_ref2);
*val_ref2 = String::from("second_layer");
println!("{}", val_ref2);
}
This is totally fine!
So then the code with the last two lines abstracted to its own function should also be totally fine.
The compiler issues an error on the following code, and I don't know how to fix it. Note, it works for the non-closure (direct call) case, it's just when I try to capture the value s in a closure that it fails. What's the right way to fix this?
fn count_letter(data : String, c : char) -> i32 {
data.chars().filter(|x| *x == c).count() as i32
}
fn main()
{
// Pretend this has to be a String, even though in this toy example it could be a str
let s = "there once was a man from nantucket".to_string();
// Works
println!("{:?}", count_letter(s, 'n'));
// error[E0507]: cannot move out of `s`, a captured variable in an `FnMut` closure
let result : Vec<(char, i32)> = ('a'..='z').map(|x| (x, count_letter(s.clone, x))).collect();
println!("{:?}", result);
}
The error is: error[E0507]: cannot move out of s, a captured variable in an FnMut closure
I gues you want this behavior:
fn count_letter(data : &str, c : char) -> i32 {
data.chars().filter(|x| *x == c).count() as i32
}
fn main()
{
// Pretend this has to be a String, even though in this toy example it could be a str
let s = "there once was a man from nantucket".to_string();
// Works
println!("{:?}", count_letter(&s, 'n'));
// Also works
let result : Vec<(char, i32)> = ('a'..='z').map(|x| (x, count_letter(&s, x))).collect();
println!("{:?}", result);
}
I'm trying to use the hyper library to make some requests. The Headers::get() method returns Option<&H>, where H is a tuple struct with one field. I can use if let Some() to destructure the Option. But how do we destructure the &H? Sure I could always access the field with .0, but I'm curious if Rust has a syntax to do this.
struct s(String);
fn f(input: &s) -> &s {
input
}
fn main() {
let my_struct1 = s("a".to_owned());
let s(foo) = my_struct1;
let my_struct2 = s("b".to_owned());
let &s(bar) = f(&my_struct2); // this does not work
let baz = &my_struct2.0; // this works
}
When you try to compile this, the Rust compiler will tell you how to fix the error with a nice message:
error[E0507]: cannot move out of borrowed content
--> <anon>:11:9
|
11 | let &s(bar) = f(&my_struct2); // this does not work
| ^^^---^
| | |
| | hint: to prevent move, use `ref bar` or `ref mut bar`
| cannot move out of borrowed content
This is needed to tell the compiler that you only want a reference to the field in the struct; the default matching will perform a move and the original struct value will no longer be valid.
Let's fix the example:
struct s(String);
fn f(input: &s) -> &s {
input
}
fn main() {
let my_struct1 = s("a".to_owned());
let s(foo) = my_struct1;
let my_struct2 = s("b".to_owned());
let &s(ref bar) = f(&my_struct2);
}
Another way is to dereference first and drop the &. I think this is preferred in Rust:
struct s(String);
fn f(input: &s) -> &s {
input
}
fn main() {
let my_struct1 = s("a".to_owned());
let s(foo) = my_struct1;
let my_struct2 = s("b".to_owned());
let s(ref bar) = *f(&my_struct2);
}
From the Rust guide:
To dereference (get the value being referred to rather than the reference itself) y, we use the asterisk (*)
So I did it:
fn main() {
let x = 1;
let ptr_y = &x;
println!("x: {}, ptr_y: {}", x, *ptr_y);
}
This gives me the same results (x=1; y=1) even without an explicit dereference:
fn main() {
let x = 1;
let ptr_y = &x;
println!("x: {}, ptr_y: {}", x, ptr_y);
}
Why? Shouldn't ptr_y print the memory address and *ptr_y print 1? Is there some kind of auto-dereference or did I miss something?
Rust usually focuses on object value (i.e. the interesting part of the contents) rather than object identity (memory addresses). The implementation of Display for &T where T implements Display defers directly to the contents. Expanding that macro manually for the String implementation of Display:
impl<'a> Display for &'a String {
fn fmt(&self, f: &mut Formatter) -> Result {
Display::fmt(&**self, f)
}
}
That is, it is just printing its contents directly.
If you care about object identity/the memory address, you can use the Pointer formatter, {:p}:
fn main() {
let x = 1;
let ptr_y = &x;
println!("x: {}, ptr_y: {}, address: {:p}", x, ptr_y, ptr_y);
}
Output:
x: 1, ptr_y: 1, address: 0x7fff4eda6a24
playground
fn main() {
let x = &42;
let address = format!("{:p}", x); // this produces something like '0x7f06092ac6d0'
println!("{}", address);
}
Suppose I'm trying to do a fancy zero-copy parser in Rust using &str, but sometimes I need to modify the text (e.g. to implement variable substitution). I really want to do something like this:
fn main() {
let mut v: Vec<&str> = "Hello there $world!".split_whitespace().collect();
for t in v.iter_mut() {
if (t.contains("$world")) {
*t = &t.replace("$world", "Earth");
}
}
println!("{:?}", &v);
}
But of course the String returned by t.replace() doesn't live long enough. Is there a nice way around this? Perhaps there is a type which means "ideally a &str but if necessary a String"? Or maybe there is a way to use lifetime annotations to tell the compiler that the returned String should be kept alive until the end of main() (or have the same lifetime as v)?
Rust has exactly what you want in form of a Cow (Clone On Write) type.
use std::borrow::Cow;
fn main() {
let mut v: Vec<_> = "Hello there $world!".split_whitespace()
.map(|s| Cow::Borrowed(s))
.collect();
for t in v.iter_mut() {
if t.contains("$world") {
*t.to_mut() = t.replace("$world", "Earth");
}
}
println!("{:?}", &v);
}
as #sellibitze correctly notes, the to_mut() creates a new String which causes a heap allocation to store the previous borrowed value. If you are sure you only have borrowed strings, then you can use
*t = Cow::Owned(t.replace("$world", "Earth"));
In case the Vec contains Cow::Owned elements, this would still throw away the allocation. You can prevent that using the following very fragile and unsafe code (It does direct byte-based manipulation of UTF-8 strings and relies of the fact that the replacement happens to be exactly the same number of bytes.) inside your for loop.
let mut last_pos = 0; // so we don't start at the beginning every time
while let Some(pos) = t[last_pos..].find("$world") {
let p = pos + last_pos; // find always starts at last_pos
last_pos = pos + 5;
unsafe {
let s = t.to_mut().as_mut_vec(); // operating on Vec is easier
s.remove(p); // remove $ sign
for (c, sc) in "Earth".bytes().zip(&mut s[p..]) {
*sc = c;
}
}
}
Note that this is tailored exactly to the "$world" -> "Earth" mapping. Any other mappings require careful consideration inside the unsafe code.
std::borrow::Cow, specifically used as Cow<'a, str>, where 'a is the lifetime of the string being parsed.
use std::borrow::Cow;
fn main() {
let mut v: Vec<Cow<'static, str>> = vec![];
v.push("oh hai".into());
v.push(format!("there, {}.", "Mark").into());
println!("{:?}", v);
}
Produces:
["oh hai", "there, Mark."]