Skip to main content

Posts

Showing posts from March, 2013

Sasa.Weak<T> - Typed Weak References

This is the ninth 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 MetadataSystem.WeakReference is a special runtime class used for collection and finalization of resources that have no other live references. The only problem is that the encapsulated value is of type "object", and so using it requires a lot more casting than it should. More often than not, a WeakReference will only encapsulate a value of one type, so this casting is often superfluous.Enter Sasa.Weak<T>, which is a struct that wraps WeakReference and provides a typed interface to encapsulated values. As a struct, it does not…

Tabular v1.0 - Import/Export Tabular Data to Excel and CSV

Awhile ago, I wrote a small library for describing, importing, and exporting tabular data to and from Excel XML, and CSV formats. I just never got around to releasing it, but I'm making a more concerted effort recently to push releases forward. The full documentation is online, and the binaries here. The license is LGPL.Describing Tabular DataTabular.dll is an assembly via which you can declaratively describe tabular data: var table1 = new Table { Name = "SomeTable", Rows = { new Row { 1, "foo", 5.7 }, new Row { 2, "bar", 99.99M }, new Row { 3, "baz", 0.0 }, } }; There are really only three classes of interest, Table, Row, and Cell. A table consists of a series of rows, a row consists of a series of cells, and each cell consists of a string value together with an alleged data type describing the string contents.The DataType enumeration is the list of recognized data strings. Cell provides numerous imp…

Sasa.Types - Runtime Types And CLR Metadata

This is the eighth 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 is a static class containing a number of extension methods on System.Type, together with extensions that mirror some of the CLR metadata instructions which aren't typically available in C#. It's available in the core Sasa.dll.Sasa.Types.ConstructorSasa.Types.Constructor accepts a lambda expression with a "new" expression designating a type's constructor. It then extracts and returns the ConstructorInfo used that expression: struct Foo { public Foo(int i) { ... } } ... var x = Types.Constructor(() => new Foo(3)); Console.Writ…

C# for Haskell and ML Programmers

An interesting question was posed to /r/Haskell today: is there a quick intro to C# from Haskell programmers?Well there are plenty of explanations of C#'s basic syntax, classes, structs, etc., but nothing that specifically addresses the functional mindset a Haskell programmer would be starting with, so I wrote a reply providing links to the various familiar concepts from functional programming found in C#, and described various caveats that might be surprising to a Haskell user. I'll reproduce the post here for posterity:I think there's a reasonable C# subset for functional programming, so if you stick to that you should be able to pick it up relatively quickly. Read up on:LINQ -- you can use the query comprehension syntax, or the regular first-class function syntax. The former is sugar for the latter.TuplesLambdas and delegates (delegates are first-class functions)Parametric polymorphism is known as generics. You can place generic parameters on methods/functions, and type…

Sasa.Strings - General String Extensions

This is the seventh 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 ExtensionsThe Sasa.Strings static class provides a number of useful extension methods on System.String, including slicing, simple tokenizing, conversions and formatting. It is available in the core Sasa.dll.Sasa.Strings.FormatSasa.Strings.Format are extension methods that wrap System.String.Format:Console.WriteLine("i = {0}".Format(1234567)); string invariant = "{0:#,##0.00}".Format(CultureInfo.InvariantCulture, 10000); Console.WriteLine(invariant); string de = "{0:#,##0.00}".Format(CultureInfo.GetCultureInfo("de-de"), …

Sasa.Numbers - Generic Number Extensions

This is the sixth 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 ValuesThe Sasa.Numbers static class provides a number of useful extensions methods on all of the CLR's number types. It is available in the core Sasa.dll.Sasa.Numbers.UpToGenerating a sequence of numbers is a pretty common operation in programming, so there's a special overload extension called Sasa.Numbers.UpTo:// iseq = 1, 2, 3 IEnumerable<int> iseq = 1.UpTo(end: 4); // iseq2 = 1, 3, 5, 7 IEnumerable<int> iseq2 = 1.UpTo(end: 8, step: 2); // dseq = 5.0, 5.5, 6.0, 6.5, 7.0 IEnumerable<double> dseq = 5.0.UpTo(end: 7.5, step: 0.5);The simplest overload simply takes the inclusive lower and exclusive upper bounds for the sequence, and th…

Sasa.Result - Handling Exceptional Values

This is the fifth 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&ltT> encapsulating the results of a computation, either it's return value, or the error it generated, if any. For instance, you could spawn a thread to perform some calculation and deposit the result into an instance of Result<T>. Sasa.Result<T> is available in the core Sasa.dll.Result<T> implements all the usual equality tests on itself, and on T, so you can perform direct comparisons to values.Sasa.Result&ltT>.ValueThe Sasa.Result<T>.Value property allows clients to obtain the value that was returned from the computation. If an error was instead generated, then this throws InvalidOperationException with the InnerException property set to …

Sasa.Option - Handling Optional Values

This is the fourth 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 is an abstraction to deal with nullable/optional values. It is available in the core Sasa.dll. Reference types are already nullable, and structs have System.Nullable, so why write yet another abstraction to deal with optional values?The answer is pretty simple: there is no other way to write a function whose generic arguments are clearly and plainly optional. This is partially complicated because C# doesn't consider type constraints when selecting method overrides, otherwise you could do something like this:int Foo<T>(T nullable) where T : class { ... } int Foo<T>(T notNullable) where T : struct { ... }The nullable overload is clear from the type information, but this type information is ne…

Sasa.Func - Type-Safe Delegate Combinators

This is the third post in my series of posts on useful Sasa abstractions:Sasa.Parsing - type-safe, extensible lexing and parsing frameworkSasa.Dynamics - type-safe polytypic/reflective programmingThis post will deal with a the Sasa.Func static class in the stand-alone core Sasa assembly. This core assembly is concerned mainly with addressing limitations in the core .NET base class libraries. For instance, it contains type-safe, null-safe and thread-safe event operations, extensions on IEnumerable, useful extensions to numbers, and so on.Sasa.Func is particularly concerned with providing type-safe extensions on delegates. You can view the whole API online. Sasa.Func is available in the core Sasa.dll.Sasa.Func.IdThe simplest starting point is Sasa.Func.Id. Use this method whenever you need a delegate that simply returns its argument. This is fairly common when using the System.Linq API. Usage: int[][] nested = new int[][] { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, }; IEnumerabl…

Sasa.Parsing - An Overview

Continuing my series of posts describing the new features in Sasa v0.9.4, I'm going to cover the new Sasa.Parsing.dll assembly. As the name implies, the assembly provides abstractions to define grammars and build parsers.Sasa.Parsing.Lexing is the namespace that provides abstractions for lexical analysis. Sasa.Parsing.Pratt is the namespace that provides an abstraction to specify a grammar that will be lexed and parsed by a Pratt parser, aka a top-down operator precedence parser.Sasa.Parsing.LexingUnderstanding lexing in Sasa starts with a very simple lexing interface that is general enough to tokenize pretty much any sort of string:/// <summary> /// Abstract lexer construction interface. /// </summary> /// <typeparam name="T">The type of a built lexer.</typeparam> /// <typeparam name="TLexerState">The lexer state.</typeparam> public interface ILexerBasic<T, TLexerState> where TLexerState : ILexerState, new() { …