Replies: 1 comment 2 replies
|
What about "copy on write"? Basically |
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary:
copy()operations are sometimes required to change fromMutArraytoArray.Wing distinguishes between immutable and mutable arrays. Here's an example of how this distinction helps catch bugs. I've made a class that stores an array of numbers, and we provide a public accessor that gives others a read-only view of the contents when they called the
view()method. When class mutates its internal array, the read-only view is left unchanged.The implementation above has a bug:
readonlyView()returnsthis._datawhich is typeMutArray, notArray. Since the internal array is being returned, the mutation would change the view, causing the assertion to fail.The Wing compiler throws an error today to tell you this. To fix the bug, you can return a copy of
this._datainstead:Our code now works. 👍
Unfortunately, sometimes the need to copy data is overly restrictive. Consider a class that calculates some data using a mutable array, and intends to return it immutably to the user:
Once
arris returned, it's not possible for it to be mutated, since it was defined as a local variable inside of the function. So, it should be safe to returnarrand implicitly convertMutArray<num>toArray<num>in this scenario. Unfortunately, this is hard for a compiler to know for sure, because even a small change to the program makes it unsafe:Here, I've pushed the mutable array
arrinside another data structure (this._secret), so it's possible to continue mutating it aftermakeDatahas returned. Soreturn arr;would not be safe in this context.As a solution, the user could return
arr.copy(), but then all of the data has to be copied, which could be an expensive operation if the array is large. How can we address this use case better?Here are the current solutions we have for these situations:
Casting
Casting can be a useful tool for situations where you want to assert to the compiler that a value is a stronger type than the compiler can guarantee. In our example above, the solution might look like this:
The compiler would check that
arr's type,MutArray<num>, is "compatible" with the target type,Array<num>(for example, we're not just casting an array into a string), and then the value is passed through, without any runtime cost.Builder pattern
Essentially the idea with this solution is we would like a way to say "within some context, we are going to allow mutation to this array -- and afterwards, it's no longer allowed". We can accomplish this using a dedicated builder class:
ArrayBuilderprovides a safe way to create an immutableArray<T>. It allows mutation to its contents for a time (without exposing its internal array), and oncebuild()is called, no further mutations are allowed.Perhaps we could add
ArrayBuilder<T>,SetBuilder<T>, andMapBuilder<T>as built-in types in the Wing standard library?All reactions