Tuesday, April 2, 2013

Sasa's Core Interfaces

This is the eleventh post in my ongoing series covering the abstractions in Sasa. Previous posts:

I covered some of Sasa's core interfaces previously, but I shall provide a more thorough treatment here.


Fundamentally, programs manipulate values. These values can often be classified into various categories depending on how they can be manipulated or computed. At the most basic level, we have a simple value represented by Sasa.IValue<T>. IValue<T> provides only a single property to access the encapsulated value:

IValue<int> x = new Immutable<int>(3);
// output:
// 3

This demonstrates the use of a simple immutable value class, but the Value property need not be so simple. It can even throw exceptions in some cases. For instance, as covered in a previous article Sasa.Result<T>.Value throws InvalidOperationException if the result was an error instead of a value.


Sasa.IRef<T>.Value extends the read-only Sasa.IValue<T> with a setter for the Sasa.IRef<T>.Value property:

IRef<int> x = new Ref<int>(3);
x.Value = 999;
// output:
// 999


Some values may or may not be present, and it's often necessary to check for the presence of a legitimate value and to obtain that value in a single step. Enter IVolatile<T>, which provides a standard interface for the common TryGetValue pattern:

IVolatile<int> withValue = new Option<int>(3);
int value;
if (withValue.TryGetValue(out value)) Console.WriteLine(value);

IVolatile<int> noValue = Option<int>.None;
if (noValue.TryGetValue(out value)) Console.WriteLine(value);

// output:
// 3


Similar to IVolatile<T>, IResolvable<T> standardizes an interface for values that may or may not be present by exporting a HasValue property:

IResolvable<int> withValue = new Option<int>(3);
if (withValue.HasValue) Console.WriteLine(withValue.Value);

IResolvable<int> noValue = Option<int>.None;
if (noValue.HasValue) Console.WriteLine(noValue.Value);

// output:
// 3


Sasa.IOptional<T> is an interface that implements IVolatile<T>, IResolvable<T>, and IValue<T>. It is implemented by many of the abstractions in Sasa that encapsulate values, like Sasa.Option<T> and Sasa.Result<T>.


Sasa.IResult<T> describes values that resolve either to a value or an error. It's an abstraction that implements IOptional<T>, IVolatile<T>, IResolvable<T>, and IValue<T>, and also exports an Error property:

IResult<int> withValue = new Result<int>(3);
if (withValue.HasValue) Console.WriteLine(withValue.Value);

IResult<int> noValue = Result.Fail<int>(new ArgumentException());
if (noValue.HasValue)
    Console.WriteLine("Error: {0}", noValue.Error.Message);

// output:
// 3
// Error: ArgumentException ...

This interface is implemented by Sasa.Result<T> and a few other abstractions in Sasa. Sasa.Result also implements the LINQ query pattern on IResult<T> instances.

No comments: