Skip to main content

Posts

Showing posts from April, 2013

Sasa.Linq.Enumerables - Extensions on IEnumerable<T>

Sasa.IO.Streams - Convenient Stream Extensions

Sasa.IO.FilePath - Easy and Safe Path Manipulations

Sasa.Operators<*> - Generic Arithmetic and Logical Operators

This is the fourteenth post in my ongoing series covering the abstractions in Sasa. Previous posts:Sasa.Parsing - type-safe, extensible lexing and parsing frameworkSasa.Dynamics - type-safe polytypic/reflective programmingSasa.Func - Type-Safe Delegate CombinatorsSasa.Option - Handling Optional ValuesSasa.Result - Handling Exceptional ValuesSasa.Numbers - Generic Number ExtensionsSasa.Strings - General String ExtensionsSasa.Types - Runtime Types And CLR MetadataSasa.Weak - Typed Weak ReferencesSasa's TuplesSasa's Core InterfacesSasa.Events - Type-Safe, Null-Safe, Thread-Safe EventsSasa.Web.Url64 - URL-Safe Base64 EncodingWhen writing generic code, it's pretty common to yearn for some generic arithmetic interface so you don't have to copy-paste the same function over and over to provide overloads for all the CLR's numeric types. Omitting a standard arithmetic interface was one of .NET's biggest mistakes in my opinion.Enter Sasa.Operators<T>, Sasa.Operators…

Fast Deep Copies in C# using Sasa.Dynamics

I've briefly discussed Sasa.Dynamics in my first announcement for the upcoming Sasa v0.9.4 release. There was some confusion about what Sasa.Dynamics really is though, since the post didn't go into much detail, or wasn't explained clearly enough. In short, Sasa.Dynamics is a framework for type-safe, blazingly fast reflection.It's useful for writing all sorts of algorithms that compute results based on the structure of types. For instance, as mentioned in the above article, Sasa.Dynamics ships with two such algorithms by default: an immutable type test, and a deep copier. Both of these algorithms are fully generic and apply to any type, and they're faster than anything you can do with standard reflection. Here's how you perform a deep copy on an object:var copy = Type<T>.Copy(originalValue);If you don't know anything about the type you're copying, you can just supply T = object. The more specific the static type information you provide to the copie…

Impressions of Code Contracts

Embroiled in a few projects right now, but one gave me the chance to explore Microsoft's code contracts a little. I was initially excited about the prospect of contracts when they were first announced, hence my crude API-compatible implementation in Sasa.Contracts which allowed me to prepare my codebases for contracts. I've now had a chance to play with the real thing, so we'll see how it holds up to reality.Going Above and BeyondAs usual, I decided to push the boundaries and try to prove properties beyond what C# and .NET can do natively via their type systems. One common nuisance on the CLR is that you can't specify a default constructor for value types. While even code contracts can't prevent someone from creating an empty struct value, you can possibly prevent the use of such an empty value:public struct NonNull<T> where T : class { readonly T value; public NonNull(T value) { Contract.Requires(value != null); this.value = v…

Sasa.Web.Url64 - URL-Safe Base64 Encoding

This is the thirteenth post in my ongoing series covering the abstractions in Sasa. Previous posts:Sasa.Parsing - type-safe, extensible lexing and parsing frameworkSasa.Dynamics - type-safe polytypic/reflective programmingSasa.Func - Type-Safe Delegate CombinatorsSasa.Option - Handling Optional ValuesSasa.Result - Handling Exceptional ValuesSasa.Numbers - Generic Number ExtensionsSasa.Strings - General String ExtensionsSasa.Types - Runtime Types And CLR MetadataSasa.Weak - Typed Weak ReferencesSasa's TuplesSasa's Core InterfacesSasa.Events - Type-Safe, Null-Safe, Thread-Safe EventsBase64 encodings are built into .NET, but the standard Base64 encoding is not safe to use in URLs. Sasa.Web.Url64 provides methods to convert to and from a URL-safe Base64 representation I refer to as Url64.Sasa.Web.Url64.FromUrl64Sasa.Web.Url64.FromUrl64 is a simple extension method on strings to convert a Url64-encoded string to a byte array: byte[] data = BitConverter.GetBytes(int.MinValue); Conso…

Sasa.Events - Type-Safe, Null-Safe, Thread-Safe Events

This is the twelfth post in my ongoing series covering the abstractions in Sasa. Previous posts:Sasa.Parsing - type-safe, extensible lexing and parsing frameworkSasa.Dynamics - type-safe polytypic/reflective programmingSasa.Func - Type-Safe Delegate CombinatorsSasa.Option - Handling Optional ValuesSasa.Result - Handling Exceptional ValuesSasa.Numbers - Generic Number ExtensionsSasa.Strings - General String ExtensionsSasa.Types - Runtime Types And CLR MetadataSasa.Weak - Typed Weak ReferencesSasa's TuplesSasa's Core InterfacesIt's well-known by now that the CLR's event model is a little broken. It requires clients using events to handle corner cases that should be handled by the runtime, particularly thread-safe event mutation and null-safe event invocation. Eric Lippert describes the issues.Sasa.Events is a static class providing methods achieving just that. It makes mutating events/delegates thread-safe (#1 thread-safety from Eric's article), and makes invocation …

Sasa's Core Interfaces

This is the eleventh post in my ongoing series covering the abstractions in Sasa. Previous posts:Sasa.Parsing - type-safe, extensible lexing and parsing frameworkSasa.Dynamics - type-safe polytypic/reflective programmingSasa.Func - Type-Safe Delegate CombinatorsSasa.Option - Handling Optional ValuesSasa.Result - Handling Exceptional ValuesSasa.Numbers - Generic Number ExtensionsSasa.Strings - General String ExtensionsSasa.Types - Runtime Types And CLR MetadataSasa.Weak - Typed Weak ReferencesSasa's TuplesI 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 Immuta…

Sasa's Tuples

This is the tenth post in my ongoing series covering the abstractions in Sasa. Previous posts:Sasa.Parsing - type-safe, extensible lexing and parsing frameworkSasa.Dynamics - type-safe polytypic/reflective programmingSasa.Func - Type-Safe Delegate CombinatorsSasa.Option - Handling Optional ValuesSasa.Result - Handling Exceptional ValuesSasa.Numbers - Generic Number ExtensionsSasa.Strings - General String ExtensionsSasa.Types - Runtime Types And CLR MetadataSasa.Weak - Typed Weak ReferencesIt's common to return multiple values from functions, and there are two common ways to do so in .NET: out parameters, and ordinary objects like structs and classes.Unfortunately, defining a whole class just to return two or three values is often overkill. Also, out parameters have some limitations, like inability to use them in lambdas, even when it's safe to do so.Enter tuples, which are types containing only generic parameters whose only purpose is to group some items together to address th…

Prim's Minimum Spanning Tree

Taking a break from Sasa blog posts, I ran into a problem that would be nicely solved by extracting the minimum spanning tree. Turns out this is pretty simple to solve naively in C# using only IEnumerable<T>: /// <summary> /// Computes the minimum spanning tree. /// </summary> /// <param name="edges">The list of edges.</param> /// <remarks> /// Given a list of edges whose vertices are consecutive numbers starting /// from 0, this extension method returns an enumerable sequence of the /// edges describing the minimum spanning tree. /// </remarks> public static IEnumerable<Edge> MinSpanTree(this IEnumerable<Edge> edges) { var span = edges.ToList(); var count = 1 + span.Max(x => Math.Max(x.From, x.To)); edges.Sort(); var vnew = new BitArray(count); vnew[0] = true; for (var i = 0; i < count; ++i) { foreach (var x in edges) { if (vnew[x.From] ^ vnew[x.To]) …