Skip to main content

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.

Sasa.IValue<T>

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);
Console.WriteLine(x.Value);
// 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

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;
Console.WriteLine(x.Value);
// output:
// 999

Sasa.IVolatile<T>.TryGetValue

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

Sasa.IResolvable<T>.HasValue

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>

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>

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(noValue.Value);
else
    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.

Comments

Popular posts from this blog

async.h - asynchronous, stackless subroutines in C

The async/await idiom is becoming increasingly popular. The first widely used language to include it was C#, and it has now spread into JavaScript and Rust. Now C/C++ programmers don't have to feel left out, because async.h is a header-only library that brings async/await to C! Features: It's 100% portable C. It requires very little state (2 bytes). It's not dependent on an OS. It's a bit simpler to understand than protothreads because the async state is caller-saved rather than callee-saved. #include "async.h" struct async pt; struct timer timer; async example(struct async *pt) { async_begin(pt); while(1) { if(initiate_io()) { timer_start(&timer); await(io_completed() || timer_expired(&timer)); read_data(); } } async_end; } This library is basically a modified version of the idioms found in the Protothreads library by Adam Dunkels, so it's not truly ground bre

Building a Query DSL in C#

I recently built a REST API prototype where one of the endpoints accepted a string representing a filter to apply to a set of results. For instance, for entities with named properties "Foo" and "Bar", a string like "(Foo = 'some string') or (Bar > 99)" would filter out the results where either Bar is less than or equal to 99, or Foo is not "some string". This would translate pretty straightforwardly into a SQL query, but as a masochist I was set on using Google Datastore as the backend, which unfortunately has a limited filtering API : It does not support disjunctions, ie. "OR" clauses. It does not support filtering using inequalities on more than one property. It does not support a not-equal operation. So in this post, I will describe the design which achieves the following goals: A backend-agnostic querying API supporting arbitrary clauses, conjunctions ("AND"), and disjunctions ("OR"). Implemen

Easy Automatic Differentiation in C#

I've recently been researching optimization and automatic differentiation (AD) , and decided to take a crack at distilling its essence in C#. Note that automatic differentiation (AD) is different than numerical differentiation . Math.NET already provides excellent support for numerical differentiation . C# doesn't seem to have many options for automatic differentiation, consisting mainly of an F# library with an interop layer, or paid libraries . Neither of these are suitable for learning how AD works. So here's a simple C# implementation of AD that relies on only two things: C#'s operator overloading, and arrays to represent the derivatives, which I think makes it pretty easy to understand. It's not particularly efficient, but it's simple! See the "Optimizations" section at the end if you want a very efficient specialization of this technique. What is Automatic Differentiation? Simply put, automatic differentiation is a technique for calcu