Replies: 1 comment 2 replies
-
What about "copy on write"? Basically |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Summary:
copy()
operations are sometimes required to change fromMutArray
toArray
.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._data
which 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._data
instead: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
arr
is 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 returnarr
and 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
arr
inside another data structure (this._secret
), so it's possible to continue mutating it aftermakeData
has 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:
ArrayBuilder
provides 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?Beta Was this translation helpful? Give feedback.
All reactions