Skip to main content

Posts

µKanren.NET - Featherweight Relational Logic Programming in C#

The µKanren paper is a nice introduction to a lightweight logic programming language which is a simplification of the miniKanren family of languages. The existing µKanren implementation in C# was a translation from Scheme, and thus is verbose, untyped with lots of casts, and non-idiomatic. I also found most of the other Kanren implementations unnecessarily obscure, heavily relying on native idioms that aren't clear to newcomers. uKanren.NET provides a clear presentation of the core principles of µKanren using only IEnumerable<T> and lambdas, showing that µKanren's search is fundamentally just a set of combinators for transforming sequences of states. The values of the sequence are sets of bound variables that satisfy a set of equations. For instance, given the following expression: Kanren.Exists(x => x == 5 | x == 6) You can read it off as saying there exists an integer value to which we can bind variable x, such that x equals either 5 or 6 [1]. Solving this eq...

NHibernate: Associations with Composite Primary Keys as Part of a Composite Primary Key

NHibernate is a pretty useful tool, but occasionally it's not entirely documented in a way that makes it's flexibility evident. Composite keys are a particularly difficult area in this regard, as evidenced by the numerous articles on the topic. Most of the existing articles cover this simply enough, but there is one uncommon corner case I have yet to see explained anywhere: a composite primary key one of whose key properties is an association with a composite key. This is probably pretty uncommon and there are ways around it, hence the lack of examples, but as a testament to NHibernate's flexibility, it's possible! Here's the example in code listing only the primary keys: public class MotorType { public Horsepower Horsepower { get; protected set; } public VoltageType VoltageType { get; protected set; } } public class Motor { public MotorType MotorType { get; protected set; } public Efficiency Efficiency { get; protected set; } } The tables look like this...

Generalized Multicast Delegates in Pure C#

.NET's delegates are a powerful and convenient abstraction available since .NET 1.1. They encapsulate a method pointer and the object the method belongs to in a single callable "function object". Multicast delegates are an extension of plain delegates, in that they encompass multiple single delegates. Invoking a multicast delegate invokes every encapsulated delegate, in the order they were added. Multicast delegates are key to event handling patterns that were a core part of the CLR nearly since its inception. If you're curious about virtual machines or CLR internals, you've perhaps wondered how multicast delegates actually work. These are the key properties of multicast delegates: They encapsulate a list of delegates of the same delegate type. Adding a delegate returns a new multicast delegate containing the new addition at the end of the list (the original is unchanged). Removing a delegate returns a new multicast delegate without the specified delegate (...

Sasa v0.14.0 Released

A quick release, fixing one bug and adding some performance improvements and some new collection types. Here's the changelog: * added a faster and more compact hash array mapped trie under Sasa.Collections.Trie to replace Sasa.Collections.Tree * added Sasa.Collections.FingerTree * added purity attributes throughout Sasa (for .NET 4) * expanded various test suites and documentation * added a persistent vector, Sasa.Collections.Vector * factored out Atomics.BeginRead/BeginWrite read/write protocol so it can be used in more flexible scenarios * Sasa.Dynamics.Type .MaybeMutable is now computed eagerly * added an efficient, mutable union-find data structure * fixed: Uris.UriDecode now handles the incorrect but common UTF16 encoding * moved Sasa.LockSet under Sasa.Concurrency.LockSet The Sasa.Collections.Tree type is no longer available, and is replaced by the faster and more appropriately named Sasa.Collections.Trie. The original tree was actually a trie, and I didn't ...

Sasa v0.13.0 Released

The latest Sasa release fixes a few bugs with MIME parsing, and adds a few new concurrency features. Here is the online documentation , or a downloadable CHM file from Sourceforge is available alongside the binaries . The binaries are also available via nuget , of course. Here's the changelog: added Sasa.Concurrency.RWLock, a truly slim concurrent read/write lock switched Sasa.Dynamics.PIC to use RWLock switched Sasa.Dynamics.PIC to rely only on arrays for performance reasons Mail message parsing now doesn't use ad-hoc means to extract a body from the attachments added Sasa.Changeable<T> which encapsulates all INotifyPropertyChanged and INotifyPropertyChanging logic with no space overhead fixed an MIME HTML parsing bug fixed regex lexing added more efficient Enums class exposing static properties for various enum properties alternate views inside multipart/related no longer incorrectly dropped added well-behaved standards conforming URI encode/decode to Sasa.Uris added ...

Immutable Sasa.Collections.Tree vs. System.Collections.Dictionary vs. C5 HashDictionary

I've previously posted about Sasa's hash-array mapped trie, but I never posted any benchmarks. I recently came across this post on Stackoverflow which provided a decent basic benchmark between .NET's default Dictionary<TKey, TValue>, the C5 collection's hash dictionary, F#'s immutable map, and .NET's new immutable collections. I slightly modified the file to remove the bench against the F# map and the new immutable collections since I'm still using VS 2010, and I added a simple warmup phase to ensure the methods have all been JIT compiled and the GC run to avoid introducing noise: static void Warmup() { var x = Tree.Make<string, object>(); var y = new C5.HashDictionary<string, object>(); var z = new Dictionary<string, object>(); z.Add("foo", "bar"); for (var i = 0; i < 100; ++i) { x = x.Add("foo" + i, "bar"); y.Add("foo" + i, "bar...

A Truly Slim Read/Write Lock in C#

It's pretty well known that the CLR's ReaderWriterLock and ReaderWriterLockSlim have unappealing performance characteristics. Each class also encapsulates signficant state, which precludes its use in fine-grained concurrency across large collections of objects. Enter Sasa.Concurrency.RWLock in the core Sasa assembly. This is the most lightweight R/W lock I could come up with, particularly in terms of resources used. It's a struct that encapsulates a simple integer that stores the number of readers and a flag indicating whether a writer is active. The interface is similar to ReaderWriterLockSlim, although there are a few differences which are needed to keep the encapsulated state so small: public struct RWLock { // this field is the only state needed by RWLock private int flags; public void EnterReadLock(); public void ExitReadLock(); public bool TryEnterReadLock(); public void EnterWriteLock(object sync); public bool TryEnterWriteLock(object sync); ...