One of the first design decision I had to take when developing several years ago the interval library in Prolog was how to represent intervals considering that I wanted to have:
- a representation as simple as possible
- both open and closed intervals
- intervals of any underlying type, including non-numerics
- natural blending in the language
- being able to handle infinity gracefully
At the time I came up with the <interval>(_, _)
term where <interval>
was ‘[)’
, ‘(]
or ‘[]’
. The ‘()’
atom was the empty interval and infinity was represented by '+inf'
and '-inf'
. I also defined a little algebra to allow for infinite operands participating to +
, -
and the like.
With the Pavings.NET library the goals are the same but the way to get there is different. Much different.
To write or not to write. That is the question
Prolog has the unification mechanism which guarantees that a term, once “assigned”, stays unchanged. Not so for .NET: here having a immutable data structure is a conscious design decision. Here are some of the trade-offs:
- An immutable structure is less prone to errors (it doesn’t have state transitions).
- An immutable structure works better with functional programming and parallelism (virtually no side effects).
- An immutable structure is less efficient (it creates a new instance for any change).
- An immutable structure should not be inherited from (it’s easy to break the substitution principle with inheritance).
- An immutable structure requires special equality/hashing logic (the reference to the object is more or less irrelevant).
Given than an interval should not be much more than a number, I opted in Pavings.NET for immutability with the provision that creating a new interval out of an old one plus some change should be inexpensive.