background preloader

Immutability

Facebook Twitter

Immutability in C# Part Eight: Even More On Binary Trees. Last year we declared a relatively simple interface to represent an immutable binary tree. We noticed that it was different from every other interface that we've declared so far, in that it really said nothing at all about the immutability of the tree. One normally thinks of immutable data types not in terms of their shape, but rather in terms of what operations may be performed on the data type. Operations are usually either to query the object somehow, or to "modify" it by producing new modified versions of the old immutable object. This binary tree interface is also unsatisfying because it does not address a problem to be solved (other than "organize this data into a binary tree", I suppose.)

It seems to be a solution in search of a problem. So let's find a problem and build a better binary tree to solve that problem. The problem I want to consider today is the implementation of immutable "dictionaries" or "maps". Let's think about it. Awesome. Luca Bolognese's WebLog : Creating an immutable value object in C# - Part V - Using a library. Other posts: Part I - Using a class Part II - Making the class better Part III - Using a structPart IV - A class with a special value In the last post we presented a variation of implementing a value object using a class. Everything works (obviously), but the amount of code to write is unpleasing.

In this post we examine a library based solution. I just describe how to use the Record class, not how it is implemented. You can read the attached implementation code (it is in functional.cs). To use the record class you need to inherit from it, as in: public class DateSpan: Record<DateTime, DateTime, bool> {...} The generic argument types represent the types that comprise the (immutable) state of the object. Public DateTime Start { get { return state.Item1; } } public DateTime End { get { return state.Item2; } } public bool HasValue { get { return state.Item3; } } This is all you have to do. For example, given the following class hierarchy: The following test case succeed:

Immutability, Purity, and Referential Transparency. How often do you write code that just works? It seems to happen so rarely that I find myself suspicious if code does just work. When was the last time that you wrote a non-trivial program that had no compile errors on the first try and then ran fine as well? If it happened recently then congratulations. If it hasn't then join the club. I recently read a post where the author describes why Haskell programs just seem to work. Can you imagine working in C# without a debugger? A Tale of Two Sorts Consider writing a function that sorts an IEnumerable<T> using the quicksort algorithm. Now imagine that ++j was in the wrong place (at the end of the block).

Would be Clearly this isn't right. The programmer might then step through the code until some state transition ends in a corrupt state. Contrast the previous definition of quicksort with the following definition: static IEnumerable<T> QuickSort<T>(this IEnumerable<T> sequence) where T : IComparable<T>{ if (! Maybe, maybe not. Fabulous Adventures In Coding : Immutability in C# Part Seven: More on Binary Trees. Fabulous Adventures In Coding : Immutability in C# Part Six: A Simple Binary Tree. Fabulous Adventures In Coding : Immutability in C# Part Four: An Immutable Queue. An immutable queue is a bit trickier than an immutable stack, but we’re tough, we can handle it. First off, the interface is straightforward; enqueuing or dequeuing results in a new queue: public interface IQueue<T> : IEnumerable<T> { bool IsEmpty { get; } T Peek(); IQueue<T> Enqueue(T value); IQueue<T> Dequeue(); } But how ever are we to implement this?

It’s not immediately obvious how to make an immutable first-in-first-out list. The first insight we need is that a stack is essentially a “backwards” queue. Static public IStack<T> Reverse<T>(this IStack<T> stack ) { IStack<T> r = Stack<T>.Empty; for (IStack<T> f = stack; ! This is an O(n) operation for a stack of size n. Now that we’ve got that we can make a first cut at our queue implementation. “Surely this is incredibly inefficient!” When we reversed the stack to dequeue it the first time, we had a stack that was in the right order for the rest of the dequeues. Isn’t this just as inefficient? Fabulous Adventures In Coding : Immutability in C# Part Three: A Covariant Immutable Stack. It's 4:30 AM where I live but this ideea just pierced through my brain, because I can't sleep This is how you can have covariance in .Net let's say you want a method that pushes an animal in a queue and pops another one from the same queue public Animal Foo<Animal+>(Queue<Animal> queue) { Animal an = new Animal(); queue.push(an); return queue.Pop(); what can you do to make the method work by passing an Queue<Giraffe>?

The method above should exactly equivalent with : public Animal Foo<T>(Queue<T> queue) where T: Animal, new() { T an = new T(); queue.Push(an); so now the first method can be called with an Queue<Giraffe> Foo<Animal+>( new Queue<Giraffe) // works because Animal+ is a T generic parameter that is of Animal type. Also this means if you write Bar<SomeType+> you don't create a closed generic definition but an open one and the instantiation is only when the method is called with a certain type. Also you need to allow references to open generic types, for example so now The whole point is: Fabulous Adventures In Coding : Immutability in C# Part Two: A Simple Immutable Stack. I wrote something like a Monad (which I have named it Monad!) In C# 3. I can achieve immutability throe it to an acceptable degree. Still I am meditating on it.

But it looks somehow interesting to me. Here is the code: private Monad (T inner) { this. __InnerHolder = inner; } private Monad () { } private readonly T __InnerHolder; private T Inner { get { return __InnerHolder; } } if (fun.IsNull ()) throw new ArgumentNullException ("fun", "'fun' can not be null get { return this; } #endregion public static partial class MonadExtra. Fabulous Adventures In Coding : Immutability in C# Part One: Kinds of Immutability. I said in an earlier post that I believe that immutable objects are the way of the future in C#. I stand by that statement while at the same time noting that it is at this point sufficiently vague as to be practically meaningless! “Immutable” means different things to different people; different kinds of immutability have different pros and cons.

I’d like to spend some time over the next few weeks talking about possible directions that C# could go to improve the developer experience when writing programs that use immutable objects, as well as giving some practical examples of the sort of immutable object programming you can do today. (Again, I want to emphasize that in these sorts of “future feature” posts we are all playfully hypothesizing and brainstorming about ideas for entirely hypothetical future versions of C#. We have not yet shipped C# 3.0 and have not announced that there will ever be any future version of the language. Realio-trulio immutability: Write-once immutability: