This post was supposed to question if toOpenArray works at all (and if it is similar to golang slices), since trying to view slice after modifying the original string showed the old values. However when I repeated the test using seq[Int], it worked just fine
{.experimental: "views".}
var seq1 = @[1,2,3,4]
var slice1 = seq1.toOpenArray(0,1)
seq1[0] = 0
echo slice1 # @[0,1] (as expected)
{.experimental: "views".}
var string1 = "abcd"
var slice1 = string1.toOpenArray(0,1)
string1[0] = 'z'
echo slice1 # @['a','b'] (expected ['z','b'])
using lent string to slice the string works properly, but it returns the whole string not just a slice
Using nim 2.2.0 on windows 11
PS: in the same vein, modifying the seq[int] by modifying the slice works as expected, but modifying the string the same way crashes the app SIGSEGV
slice1[0] = 0 # Works with seq[int]
slice1[0] = 'z' # Crashes with string
It should error with both, but sequences and strings from literals are immutable. You need to call prepareMutation to make it copy to a new sequence.
{.experimental: "views".}
var string1 = "abcd"
string1.prepareMutation()
var slice1 = string1.toOpenArray(0,1)
string1[0] = 'z'
assert slice1 == ['z', 'b']
Thanks! It works now
However I am not sure I get how strings and seq are immutable using var Is the original literal dropped and a new seq/string are created when updating elements/chars?
Update: preparemutation changes string1's address, and its implementation involves copying its data to a new nimstringv2 type. Afterwards, the new string behaves as expected, with regards to mutability and index pointer addresses.
Is all of this necessary because of copy on write?
Another update: I tried to avoid the avoid the first copy by first initiating an empty string, preparemutate it, then assign it the value i wanted, and the view slice is once again not linked (['a','b'] instead of ['z','b'], and the first index's address of the string changes after mutating it).
I guess preparemutate does not change the underlying string to become mutable. When should I use preparemutate? If i think there would be an underlying realloc somewhere?
Like ElegantBeef said, the original string is a literal. It's stored in the read-only protected section of memory. It's essentially a part of the program code. You can't change anything there, so you have to force a copy to the data section of memory. That's what prepareMutation() does.
https://github.com/nim-lang/Nim/blob/version-2-2/lib/system/strs_v2.nim#L197