The Stack Overflow podcast is back! Listen to an interview with our new CEO.
4 added 16 characters in body
source | link

I might have an overly low-level view of this and likely because I'm using C and C++ which don't exactly make it so straightforward to make everything immutable, but I see immutable data types as an optimization detail in order to write more efficient functions devoid of side effects and be able to very easily provide features like undo systems and non-destructive editing.

For example, this could be enormously expensive:

/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);

... if Mesh isn't designed to be a persistent data structure and was, instead, a data type which required copying it in full (which could span gigabytes in some scenario) even if all we're going to be doing is changing a part of it (like in the above scenario where we only modify vertex positions).

So that's when I reach for immutability and design the data structure to allow unmodified portions of it to be shallow copied and reference counted, to allow the above function to be reasonably efficient without having to deep copy entire meshes around while still being able to write the function to be free of side effects which dramatically simplifies thread-safety, exception-safety, the ability to undo the operation, apply it non-destructively, etc.

In my case it's too costly (at least from a productivity standpoint) to make everything immutable, so I save it for the classes which are too expensive to deep copy in full. Those classes are usually hefty data structures like meshes and images and I generally use a mutable interface to express changes to them through a "builder" object to get a new immutable copy. And I'm not doing that so much to try to achieve immutable guarantees at the central level of the class so much as helping me to use the class in functions that can be free of side effects. My desire to make Mesh immutable above is not directly to make meshes immutable, but to allow easily writing functions free of side effects that returninput a mesh and output a new meshesone without paying a massive memory and computational cost in exchange.

As a result I only have 4 immutable data types in my entire codebase, and they're all hefty data structures, but I use them heavily to help me write functions which are free of side effects. This answer might be applicable if, like me, you're working in a language that doesn't make it so easy to make everything immutable. In that case, you can shift your focus towards making the bulk of your functions avoid side effects, at which point you might want to make select data structures immutable, PDS types, as an optimization detail to avoid the expensive full copies. Meanwhile when I have a function like this:

/// @return The v1 * v2.
Vector3f vec_mul(Vector3f v1, Vector3f v2);

... then I have no temptation to make vectors immutable since they're cheap enough to just copy in full. There's no performance advantage to be gained here by turning Vectors into immutable structures that can shallow copy unmodified parts. Such costs would outweigh the cost of just copying the entire vector.

I might have an overly low-level view of this and likely because I'm using C and C++ which don't exactly make it so straightforward to make everything immutable, but I see immutable data types as an optimization detail in order to write more efficient functions devoid of side effects and be able to very easily provide features like undo systems and non-destructive editing.

For example, this could be enormously expensive:

/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);

... if Mesh isn't designed to be a persistent data structure and was, instead, a data type which required copying it in full (which could span gigabytes in some scenario) even if all we're going to be doing is changing a part of it (like in the above scenario where we only modify vertex positions).

So that's when I reach for immutability and design the data structure to allow unmodified portions of it to be shallow copied and reference counted, to allow the above function to be reasonably efficient without having to deep copy entire meshes around while still being able to write the function to be free of side effects which dramatically simplifies thread-safety, exception-safety, the ability to undo the operation, apply it non-destructively, etc.

In my case it's too costly (at least from a productivity standpoint) to make everything immutable, so I save it for the classes which are too expensive to deep copy in full. Those classes are usually hefty data structures like meshes and images and I generally use a mutable interface to express changes to them through a "builder" object to get a new immutable copy. And I'm not doing that so much to try to achieve immutable guarantees at the central level of the class so much as helping me to use the class in functions that can be free of side effects. My desire to make Mesh immutable above is not directly to make meshes immutable, but to allow easily writing functions free of side effects that return new meshes without paying a massive memory and computational cost in exchange.

As a result I only have 4 immutable data types in my entire codebase, and they're all hefty data structures, but I use them heavily to help me write functions which are free of side effects. This answer might be applicable if, like me, you're working in a language that doesn't make it so easy to make everything immutable. In that case, you can shift your focus towards making the bulk of your functions avoid side effects, at which point you might want to make select data structures immutable, PDS types, as an optimization detail to avoid the expensive full copies. Meanwhile when I have a function like this:

/// @return The v1 * v2.
Vector3f vec_mul(Vector3f v1, Vector3f v2);

... then I have no temptation to make vectors immutable since they're cheap enough to just copy in full.

I might have an overly low-level view of this and likely because I'm using C and C++ which don't exactly make it so straightforward to make everything immutable, but I see immutable data types as an optimization detail in order to write more efficient functions devoid of side effects and be able to very easily provide features like undo systems and non-destructive editing.

For example, this could be enormously expensive:

/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);

... if Mesh isn't designed to be a persistent data structure and was, instead, a data type which required copying it in full (which could span gigabytes in some scenario) even if all we're going to be doing is changing a part of it (like in the above scenario where we only modify vertex positions).

So that's when I reach for immutability and design the data structure to allow unmodified portions of it to be shallow copied and reference counted, to allow the above function to be reasonably efficient without having to deep copy entire meshes around while still being able to write the function to be free of side effects which dramatically simplifies thread-safety, exception-safety, the ability to undo the operation, apply it non-destructively, etc.

In my case it's too costly (at least from a productivity standpoint) to make everything immutable, so I save it for the classes which are too expensive to deep copy in full. Those classes are usually hefty data structures like meshes and images and I generally use a mutable interface to express changes to them through a "builder" object to get a new immutable copy. And I'm not doing that so much to try to achieve immutable guarantees at the central level of the class so much as helping me to use the class in functions that can be free of side effects. My desire to make Mesh immutable above is not directly to make meshes immutable, but to allow easily writing functions free of side effects that input a mesh and output a new one without paying a massive memory and computational cost in exchange.

As a result I only have 4 immutable data types in my entire codebase, and they're all hefty data structures, but I use them heavily to help me write functions which are free of side effects. This answer might be applicable if, like me, you're working in a language that doesn't make it so easy to make everything immutable. In that case, you can shift your focus towards making the bulk of your functions avoid side effects, at which point you might want to make select data structures immutable, PDS types, as an optimization detail to avoid the expensive full copies. Meanwhile when I have a function like this:

/// @return The v1 * v2.
Vector3f vec_mul(Vector3f v1, Vector3f v2);

... then I have no temptation to make vectors immutable since they're cheap enough to just copy in full. There's no performance advantage to be gained here by turning Vectors into immutable structures that can shallow copy unmodified parts. Such costs would outweigh the cost of just copying the entire vector.

3 added 379 characters in body
source | link

I might have an overly low-level view of this and likely because I'm using C and C++ which don't exactly make it so straightforward to make everything immutable, but I see immutable data types as an optimization detail in order to write more efficient functions devoid of side effects and be able to very easily provide features like undo systems and non-destructive editing.

For example, this could be enormously expensive:

/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);

... if Mesh isn't designed to be a persistent data structure and was, instead, a data type which required copying it in full (which could span gigabytes in some scenario) even if all we're going to be doing is changing a part of it (like in the above scenario where we only modify vertex positions).

So that's when I reach for immutability and design the data structure to allow unmodified portions of it to be shallow copied and reference counted, to allow the above function to be reasonably efficient without having to deep copy entire meshes around while still being able to write the function to be free of side effects which dramatically simplifies thread-safety, exception-safety, the ability to undo the operation, apply it non-destructively, etc.

In my case it's too costly (at least from a productivity standpoint) to make everything immutable, so I save it for the classes which are too expensive to deep copy in full. Those classes are usually hefty data structures like meshes and images and I generally use a mutable interface to express changes to them through a "builder" object to get a new immutable copy. And I'm not doing that so much to try to achieve immutable guarantees at the central level of the class so much as helping me to use the class in functions that can be free of side effects. My desire to make Mesh immutable above is not directly to make meshes immutable, but to allow easily writing functions free of side effects that return new meshes without paying a massive memory and computational cost in exchange.

As a result I only have 4 immutable data types in my entire codebase, and they're all hefty data structures, but I use them heavily to help me write functions which are free of side effects. This answer might be applicable if, like me, you're working in a language that doesn't make it so easy to make everything immutable. In that case, you can shift your focus towards making the bulk of your functions avoid side effects, at which point you might want to make select data structures immutable, PDS types, as an optimization detail to avoid the expensive full copies. Meanwhile when I have a function like this:

/// @return The v1 * v2.
Vector3f vec_mul(Vector3f v1, Vector3f v2);

... then I have no temptation to make vectors immutable since they're cheap enough to just copy in full.

I might have an overly low-level view of this and likely because I'm using C and C++ which don't exactly make it so straightforward to make everything immutable, but I see immutable data types as an optimization detail in order to write more efficient functions devoid of side effects and be able to very easily provide features like undo systems and non-destructive editing.

For example, this could be enormously expensive:

/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);

... if Mesh isn't designed to be a persistent data structure and was, instead, a data type which required copying it in full (which could span gigabytes in some scenario) even if all we're going to be doing is changing a part of it (like in the above scenario where we only modify vertex positions).

So that's when I reach for immutability and design the data structure to allow unmodified portions of it to be shallow copied and reference counted, to allow the above function to be reasonably efficient without having to deep copy entire meshes around while still being able to write the function to be free of side effects which dramatically simplifies thread-safety, exception-safety, the ability to undo the operation, apply it non-destructively, etc.

In my case it's too costly (at least from a productivity standpoint) to make everything immutable, so I save it for the classes which are too expensive to deep copy in full. Those classes are usually hefty data structures like meshes and images and I generally use a mutable interface to express changes to them through a "builder" object to get a new immutable copy. And I'm not doing that so much to try to achieve immutable guarantees at the central level of the class so much as helping me to use the class in functions that can be free of side effects. My desire to make Mesh immutable above is not directly to make meshes immutable, but to allow easily writing functions free of side effects that return new meshes without paying a massive memory and computational cost in exchange.

As a result I only have 4 immutable data types in my entire codebase, and they're all hefty data structures, but I use them heavily to help me write functions which are free of side effects.

I might have an overly low-level view of this and likely because I'm using C and C++ which don't exactly make it so straightforward to make everything immutable, but I see immutable data types as an optimization detail in order to write more efficient functions devoid of side effects and be able to very easily provide features like undo systems and non-destructive editing.

For example, this could be enormously expensive:

/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);

... if Mesh isn't designed to be a persistent data structure and was, instead, a data type which required copying it in full (which could span gigabytes in some scenario) even if all we're going to be doing is changing a part of it (like in the above scenario where we only modify vertex positions).

So that's when I reach for immutability and design the data structure to allow unmodified portions of it to be shallow copied and reference counted, to allow the above function to be reasonably efficient without having to deep copy entire meshes around while still being able to write the function to be free of side effects which dramatically simplifies thread-safety, exception-safety, the ability to undo the operation, apply it non-destructively, etc.

In my case it's too costly (at least from a productivity standpoint) to make everything immutable, so I save it for the classes which are too expensive to deep copy in full. Those classes are usually hefty data structures like meshes and images and I generally use a mutable interface to express changes to them through a "builder" object to get a new immutable copy. And I'm not doing that so much to try to achieve immutable guarantees at the central level of the class so much as helping me to use the class in functions that can be free of side effects. My desire to make Mesh immutable above is not directly to make meshes immutable, but to allow easily writing functions free of side effects that return new meshes without paying a massive memory and computational cost in exchange.

As a result I only have 4 immutable data types in my entire codebase, and they're all hefty data structures, but I use them heavily to help me write functions which are free of side effects. This answer might be applicable if, like me, you're working in a language that doesn't make it so easy to make everything immutable. In that case, you can shift your focus towards making the bulk of your functions avoid side effects, at which point you might want to make select data structures immutable, PDS types, as an optimization detail to avoid the expensive full copies. Meanwhile when I have a function like this:

/// @return The v1 * v2.
Vector3f vec_mul(Vector3f v1, Vector3f v2);

... then I have no temptation to make vectors immutable since they're cheap enough to just copy in full.

2 added 190 characters in body
source | link

I might have an overly low-level view of this and likely because I'm using C and C++ which don't exactly make it so straightforward to make everything immutable, but I see immutable data types as an optimization detail in order to write more efficient functions devoid of side effects and be able to very easily provide features like undo systems and non-destructive editing.

For example, this could be enormously expensive:

/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);

... if Mesh isn't designed to be a persistent data structure and was, instead, a data type which required copying it in full (which could span gigabytes in some scenario) even if all we're going to be doing is changing a part of it (like in the above scenario where we only modify vertex positions).

So that's when I reach for immutability and design the data structure to allow unmodified portions of it to be shallow copied and reference counted, to allow the above function to be reasonably efficient without having to deep copy entire meshes around while still being able to write the function to be free of side effects which dramatically simplifies thread-safety, exception-safety, the ability to undo the operation, apply it non-destructively, etc.

In my case it's too costly (at least from a productivity standpoint) to make everything immutable, so I save it for the classes which are too expensive to deep copy in full. Those classes are usually hefty data structures like meshes and images and I generally use a mutable interface to express changes to them through a "builder" object to get a new immutable copy. And I'm not doing that so much to try to achieve immutable guarantees at the central level of the class so much as helping me to use the class in functions that can be free of side effects. My desire to make Mesh immutable above is not directly to make meshes immutable, but to allow easily writing functions free of side effects that return new meshes without paying a massive memory and computational cost in exchange.

As a result I only have 4 immutable data types in my entire codebase, and they're all hefty data structures, but I use them heavily to help me write functions which are free of side effects.

I might have an overly low-level view of this and likely because I'm using C and C++ which don't exactly make it so straightforward to make everything immutable, but I see immutable data types as an optimization detail in order to write more efficient functions devoid of side effects and be able to very easily provide features like undo systems and non-destructive editing.

For example, this could be enormously expensive:

/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);

... if Mesh isn't designed to be a persistent data structure and was, instead, a data type which required copying it in full (which could span gigabytes in some scenario) even if all we're going to be doing is changing a part of it (like in the above scenario where we only modify vertex positions).

So that's when I reach for immutability and design the data structure to allow unmodified portions of it to be shallow copied and reference counted, to allow the above function to be reasonably efficient without having to deep copy entire meshes around while still being able to write the function to be free of side effects which dramatically simplifies thread-safety, exception-safety, the ability to undo the operation, apply it non-destructively, etc.

In my case it's too costly to make everything immutable, so I save it for the classes which are too expensive to deep copy in full. Those classes are usually hefty data structures like meshes and images and I generally use a mutable interface to express changes to them through a "builder" object to get a new immutable copy.

I might have an overly low-level view of this and likely because I'm using C and C++ which don't exactly make it so straightforward to make everything immutable, but I see immutable data types as an optimization detail in order to write more efficient functions devoid of side effects and be able to very easily provide features like undo systems and non-destructive editing.

For example, this could be enormously expensive:

/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);

... if Mesh isn't designed to be a persistent data structure and was, instead, a data type which required copying it in full (which could span gigabytes in some scenario) even if all we're going to be doing is changing a part of it (like in the above scenario where we only modify vertex positions).

So that's when I reach for immutability and design the data structure to allow unmodified portions of it to be shallow copied and reference counted, to allow the above function to be reasonably efficient without having to deep copy entire meshes around while still being able to write the function to be free of side effects which dramatically simplifies thread-safety, exception-safety, the ability to undo the operation, apply it non-destructively, etc.

In my case it's too costly (at least from a productivity standpoint) to make everything immutable, so I save it for the classes which are too expensive to deep copy in full. Those classes are usually hefty data structures like meshes and images and I generally use a mutable interface to express changes to them through a "builder" object to get a new immutable copy. And I'm not doing that so much to try to achieve immutable guarantees at the central level of the class so much as helping me to use the class in functions that can be free of side effects. My desire to make Mesh immutable above is not directly to make meshes immutable, but to allow easily writing functions free of side effects that return new meshes without paying a massive memory and computational cost in exchange.

As a result I only have 4 immutable data types in my entire codebase, and they're all hefty data structures, but I use them heavily to help me write functions which are free of side effects.

1
source | link