Hacker News new | past | comments | ask | show | jobs | submit login

This might be the first time I’ve seen a good use for &mut &T, very cool!

For those of you not well-versed in Rust, this is a mutable pointer to an immutable string. This means that you can change the part of the string you’re pointing at, but you can’t change the underlying string itself.




What does that mean? Is it equivalent to the pointer starting out (say) pointing to the first letter of the string, but being able to "walk"/iterate along the length of the string?


EDIT: adjusted the diagram to make it more clear that we're not mutating the &str

Here's some string data, in memory somewhere:

    Hello world   
A `&str` is a pointer, length combo. The pointer points to the start of the string, the length says how many bytes there are:

    (p, 11)           
     |                
      \ 
       |
       V              
       Hello world
      
 A `&mut T` is a pointer, so a `&mut &str` looks like this:

     p
     |
     V
    (p, 11)           
     |                
      \ 
       |
       V              
       Hello world
 
 Since it's mutable, this means we can re-assign what it points to, and create a new `&str` to the later part of the string:
 
     p
     \------\
             V
    (p, 11) (p, 5)           
     |       |                
      \      |
       |     |
       V     V         
       Hello world
 
 Since the inner &str is immutable, we can't change the underling string.
 
 Hope that helps!


Re: your edit, isn't mutating the `&str` exactly what we're doing? Your new diagram implies that `input` itself is mutable and that's what's being overwritten, but that's not what `input: &mut &str` means nor would it even work because the mutation wouldn't be visible to the caller...?


.... uuuuugh dammit you are correct. Thanks. I can't mutate the parent post, sadly, so have an upvote and hopefully you sit at the top.

I did draw the right thing at first, then convinced myself I was wrong and "fixed" it. Tricky!


I want to make sure I understand this. The original pointer &str does not own the "Hello world" variable but is a reference to it. The new &mut T pointer takes ownership of the &str reference so the original specified (p,11) would be destroyed/overwritten when changed to (p,5). The &mut T cannot edit the underlying string because it the reference it owns is a nonmutable reference. Even if the underlying string, "Hello world" was a mutable str variable, then &mut T could not access it since it was provided and immutable reference &str as its type.

If we provided a mutable pointer to the &mut T, would the mutable pointer would take ownership of the "Hello world"? If so, would Rust then throw a compiler error because we've created a situation where we can orphan part of "Hello world"?


> The original pointer &str does not own the "Hello world" variable but is a reference to it.

Correct.

> The new &mut T pointer takes ownership of the &str reference

&T/&mut T never take ownership. It is true that &mut T must be exclusive, so it's sort of like "temporary ownership", but the underlying T won't be destroyed when the reference goes out of scope.

> so the original specified (p,11) would be destroyed/overwritten when changed to (p,5).

The original &str will still live as long as it lives; we're creating a new one, and changing the &mut to point to it, not overwriting the existing one.

> The &mut T cannot edit the underlying string because it the reference it owns is a nonmutable reference. Even if the underlying string, "Hello world" was a mutable str variable, then &mut T could not access it since it was provided and immutable reference &str as its type.

Correct.

> If we provided a mutable pointer to the &mut T, would the mutable pointer would take ownership of the "Hello world"? If so, would Rust then throw a compiler error because we've created a situation where we can orphan part of "Hello world"?

No, &mut T never takes ownership.

Hope that helps! Happy to answer more questions if you've got them.


Turns out I was slightly wrong, see above. It's still true that no ownership is taken, but we are mutating the &str.


Awesome, thank you for the explanation. I'm still trying to really understand Rust ownership and pointers.


Thank you, yes.

Is there a binding between the "top" pointer &mut T, and the string which the pointer/length pair points to?

Can we change our pointer to point somewhere else entirely, say a newly allocated string "goodbye, world"?

  p1
   \------\
           V
  (p2, 11) (p3, 13)
  |          \
  |           \
  |            \
  V             V
  Hello World   Goodbye World


There's no inherent connection; you could absolutely do this.


To restrict in the manner that the person above described would require some kind of const parameter in the type, no? The type would need to be parameterized over the `&str` to ensure that slices could only be taken from that particular string.


I believe that’s correct.


So it’s basically like a Span in C# if I understood correctly?


I am not familiar with the in-memory representation of Slice, but conceptually at least, yes. We call &str a "string slice" and &[T] more generally a "slice".

EDIT: apparently you just edited from Slice to Span, reading https://msdn.microsoft.com/en-us/magazine/mt814808.aspx

> First, Span<T> is a value type containing a ref and a length, defined approximately as follows:

Yep, exactly the same as Span<T> then.


Sorry, I wrote Slice instead of Span in the original comment... Slice is the method that returns a Span that is the equivalent of this rust concept as far as I can tell. At some point in the future I’ll need to delve in rust, it’s quite fascinating, but sadly I don’t have much time nowadays :(


It's all good, on both counts! We'll still be around when you find the time :)


It's actually like a ref Span argument, if my understanding of it is correct.

&[T] is like Span<T>, while a &mut &[T] is like a reference to a Span<T>.


Yeah I do that in a command line interface module for some firmware I wrote. No heap, very limited memory, solution string functions that understand the concept of white space delimited tokens. You just walk the pointer down the input string without modifying it.


It means you can change the string to which the pointer is currently associated.

Edit: I removed my initial “no.”


But in this case, it will be used the way that e12e described.


Ah. I may have misunderstood what they were suggesting.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: