Great questions! To be honest I don't have enough knowledge of the MRI internals yet to be able to answer these 100% correctly. Maybe I'll write a follow up post or an update to this one explaining these issues when I have time for more research.
But for today:
1. str2 = str doesn't actually create a new string. RString represents a string value, not a string object. So str2=str creates a new RString because that essentially defines what str2's value refers to… Think of RString as an internal pointer to the value that str or str2 is referring to. Sorry - not a good explanation :(
2. How are shared RStrings modified? Not sure yet, but I'm curious to find out. Will let you know on my site somehow.
3. Yes, simply calling str2 = str or in a variety of other ways will do it.
I'm 99% sure you're wrong about 1). The internal pointer is the VALUE that is pointing to the struct RString. `str2 = str` will make another VALUE point to the same struct RString. Consider
I'm fairly sure that implies that str and str2 share everything including the RString object, so it couldn't really have one of str/str2 have a field that points to the other.
I am not sure about 2) and 3) but I'd expect some copy-on-write mechanism based on a flag field in the RBasic struct, and taking substrings might be O(1) thanks to sharing too.
In Ruby, most classes (including String) are reference types. This is why `str2 = str` doesn't create a new string. It doesn't create a new RString either - str and str2 are both pointers to the same RString struct.
Comments
Why would str2=str create a new string?
How are RStrings modified when they are referenced by other shared RStrings?
Is there any way to create a shared RString other than calling .dup?
Great questions! To be honest I don't have enough knowledge of the MRI internals yet to be able to answer these 100% correctly. Maybe I'll write a follow up post or an update to this one explaining these issues when I have time for more research.
But for today:
1. str2 = str doesn't actually create a new string. RString represents a string value, not a string object. So str2=str creates a new RString because that essentially defines what str2's value refers to… Think of RString as an internal pointer to the value that str or str2 is referring to. Sorry - not a good explanation :(
2. How are shared RStrings modified? Not sure yet, but I'm curious to find out. Will let you know on my site somehow.
3. Yes, simply calling str2 = str or in a variety of other ways will do it.
I'm 99% sure you're wrong about 1). The internal pointer is the VALUE that is pointing to the struct RString. `str2 = str` will make another VALUE point to the same struct RString. Consider
I'm fairly sure that implies that str and str2 share everything including the RString object, so it couldn't really have one of str/str2 have a field that points to the other.I am not sure about 2) and 3) but I'd expect some copy-on-write mechanism based on a flag field in the RBasic struct, and taking substrings might be O(1) thanks to sharing too.
Here's a better explanation for #1:
In Ruby, most classes (including String) are reference types. This is why `str2 = str` doesn't create a new string. It doesn't create a new RString either - str and str2 are both pointers to the same RString struct.
AFAIK str2 = str will just share the RVALUE-Pointer.
I think to actually see shared strings behavior, you would have to do str2 = str.clone or str2 = str[0..-1].