Skip to main content

Posts

Showing posts from April, 2013

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

This is the seventeenth post in my ongoing series covering the abstractions in Sasa . Previous posts: Sasa.Parsing - type-safe, extensible lexing and parsing framework Sasa.Dynamics - type-safe polytypic/reflective programming Sasa.Func - Type-Safe Delegate Combinators Sasa.Option - Handling Optional Values Sasa.Result - Handling Exceptional Values Sasa.Numbers - Generic Number Extensions Sasa.Strings - General String Extensions Sasa.Types - Runtime Types And CLR Metadata Sasa.Weak - Typed Weak References Sasa's Tuples Sasa's Core Interfaces Sasa.Events - Type-Safe, Null-Safe, Thread-Safe Events Sasa.Web.Url64 - URL-Safe Base64 Encoding Sasa.Operators<T> - Generic Arithmetic and Logical Operators Sasa.IO.FilePath - Easy and Safe Path Manipulations Sasa.IO.Streams - Convenient Stream Extensions In my opinion, the release of .NET 3.5 and LINQ to Objects was one of the greatest productivity and safety enhancements to .NET since its inception. It enabled th

Sasa.IO.Streams - Convenient Stream Extensions

This is the sixteenth post in my ongoing series covering the abstractions in Sasa . Previous posts: Sasa.Parsing - type-safe, extensible lexing and parsing framework Sasa.Dynamics - type-safe polytypic/reflective programming Sasa.Func - Type-Safe Delegate Combinators Sasa.Option - Handling Optional Values Sasa.Result - Handling Exceptional Values Sasa.Numbers - Generic Number Extensions Sasa.Strings - General String Extensions Sasa.Types - Runtime Types And CLR Metadata Sasa.Weak - Typed Weak References Sasa's Tuples Sasa's Core Interfaces Sasa.Events - Type-Safe, Null-Safe, Thread-Safe Events Sasa.Web.Url64 - URL-Safe Base64 Encoding Sasa.Operators<T> - Generic Arithmetic and Logical Operators Sasa.IO.FilePath - Easy and Safe Path Manipulations Streams are a pervasive component of .NET I/O, but the standard stream interface is missing a few convenient extensions, if only needed for testing and debugging purposes. Sasa.IO.Streams provides a few simple e

Sasa.IO.FilePath - Easy and Safe Path Manipulations

This is the fifteenth post in my ongoing series covering the abstractions in Sasa . Previous posts: Sasa.Parsing - type-safe, extensible lexing and parsing framework Sasa.Dynamics - type-safe polytypic/reflective programming Sasa.Func - Type-Safe Delegate Combinators Sasa.Option - Handling Optional Values Sasa.Result - Handling Exceptional Values Sasa.Numbers - Generic Number Extensions Sasa.Strings - General String Extensions Sasa.Types - Runtime Types And CLR Metadata Sasa.Weak - Typed Weak References Sasa's Tuples Sasa's Core Interfaces Sasa.Events - Type-Safe, Null-Safe, Thread-Safe Events Sasa.Web.Url64 - URL-Safe Base64 Encoding Sasa.Operators<T> - Generic Arithmetic and Logical Operators One persistent difficulty in dealing with IO in .NET is path handling. .NET exposes a platform's directory separator characters, but really this sort of thing should be automated. Furthermore, paths are considered simple strings and so concatenating fragments c

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 framework Sasa.Dynamics - type-safe polytypic/reflective programming Sasa.Func - Type-Safe Delegate Combinators Sasa.Option - Handling Optional Values Sasa.Result - Handling Exceptional Values Sasa.Numbers - Generic Number Extensions Sasa.Strings - General String Extensions Sasa.Types - Runtime Types And CLR Metadata Sasa.Weak - Typed Weak References Sasa's Tuples Sasa's Core Interfaces Sasa.Events - Type-Safe, Null-Safe, Thread-Safe Events Sasa.Web.Url64 - URL-Safe Base64 Encoding When 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.O

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 t

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 Beyond As 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.va

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 framework Sasa.Dynamics - type-safe polytypic/reflective programming Sasa.Func - Type-Safe Delegate Combinators Sasa.Option - Handling Optional Values Sasa.Result - Handling Exceptional Values Sasa.Numbers - Generic Number Extensions Sasa.Strings - General String Extensions Sasa.Types - Runtime Types And CLR Metadata Sasa.Weak - Typed Weak References Sasa's Tuples Sasa's Core Interfaces Sasa.Events - Type-Safe, Null-Safe, Thread-Safe Events Base64 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.FromUrl64 Sasa.Web.Url64.FromUrl64 is a simple extension method on strings to convert a Url64-encoded string to a byte array: byte[] data = BitC

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 framework Sasa.Dynamics - type-safe polytypic/reflective programming Sasa.Func - Type-Safe Delegate Combinators Sasa.Option - Handling Optional Values Sasa.Result - Handling Exceptional Values Sasa.Numbers - Generic Number Extensions Sasa.Strings - General String Extensions Sasa.Types - Runtime Types And CLR Metadata Sasa.Weak - Typed Weak References Sasa's Tuples Sasa's Core Interfaces It'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 a

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 framework Sasa.Dynamics - type-safe polytypic/reflective programming Sasa.Func - Type-Safe Delegate Combinators Sasa.Option - Handling Optional Values Sasa.Result - Handling Exceptional Values Sasa.Numbers - Generic Number Extensions Sasa.Strings - General String Extensions Sasa.Types - Runtime Types And CLR Metadata Sasa.Weak - Typed Weak References Sasa's Tuples 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:

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 framework Sasa.Dynamics - type-safe polytypic/reflective programming Sasa.Func - Type-Safe Delegate Combinators Sasa.Option - Handling Optional Values Sasa.Result - Handling Exceptional Values Sasa.Numbers - Generic Number Extensions Sasa.Strings - General String Extensions Sasa.Types - Runtime Types And CLR Metadata Sasa.Weak - Typed Weak References It'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

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])