Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Wednesday, August 11, 2010

OOP Virtualization vs. F# Discriminated Unions

This post continues my theme of learning to think outside the OOP (object-oriented programming) box. In particular, it examines how F# discriminated unions can simplify small components in a way that captures the flavor of a hierarchy, yet without the complexity and fluff of an explicit OOP hierarchy. (Mark Pearl has an excellent post this week on a similar theme: function programming recursion vs. iterative constructs.)

Don’t get me wrong, OOP is a great paradigm, F# implements it well, and OOP is absolutely essential when working within the .NET ecosystem. It’s just that sometimes a class hierarchy can be overkill.

I picked C# to implement the OOP example, but I don’t want the takeaway from this post to be C#==Bad/F#=Good. I want to illustrate the principles, and assume readers will be more familiar with C# than with C++ or F# OOP constructs. (The example does, however, illustrate how the “ceremony” that is C#’s lineage from C can make code more difficult to read. To be fair, the brain trusts behind C# and C++ are working to reduce some of this.)

My example is a rudimentary model of logic gates. Since the inputs to the gates are fixed, it’s not particularly useful, but I wanted to keep things simple.

Here is the OOP implementation. It models the problem using an abstract base class to model a general logic gate, and concrete overrides to model And and Or gates. As you can see, there’s quite a lot of complexity and page space devoted even to this simple implementation. (As always, all the code here is presented "as-is" and without warranty or implied fitness of any kind; use at your own risk.)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace ConsoleApplication3
{
  // Model.
 
  public abstract class Gate  
  {
    public List<bool> Input { get; private set; }
 
    public Gate (List<bool> input)
    {
      Input = new List<bool>(input);
    }
 
 
    public abstract bool Test ();
  }
 
 
  public class And : Gate 
  {
    public And (List<bool> input) :
      base(input) {}
 
    public override bool Test ()
    {
      return !Input.Contains(false);
    }
  }
 
 
  public class Or : Gate 
  {
    public Or (List<bool> input) :
      base(input) {}
 
    public override bool Test ()
    {
      return Input.Contains(true);
    }
  }
 
  // Example.
 
  class Program
  {
    static void Main(string[] args) 
    {
      bool baf = 
        (new And(new List<bool>() 
          {true,false,true})).Test();
 
      bool bat = 
        (new And(new List<bool>() 
          {true,true,true})).Test();
 
      bool bof = 
        (new And(new List<bool>() 
          {false,false,false})).Test();
 
      bool bot = 
        (new And(new List<bool>() 
          {false,true,false})).Test();
 
      Console.WriteLine("Your breakpoint here.");
    }
  }
}


And here is the F# discriminated union example, along with a “bonus” example showing the extension of the idea to active patterns. To me, at least, it looks a lot more straightforward and should be easier to understand when first encountered. It also takes up a lot less page space.

// Model.
 
type Gate = 
  | And of bool list
  | Or of bool list
 
let test = function
  | And(l) -> List.exists ((=) false) l |> not
  | Or(l) -> List.exists ((=) true) l 
 
// Example.
 
let baf = And([true;false;true]) |> test
let bat = And([true;true;true]) |> test
let bof = Or([false;false;false]) |> test
let bot = Or([false;true;false]) |> test
 
// Bonus extension: active pattern.
 
let (|Test|) (g:Gate) = test g
 
let fired = function | Test(b) -> b
 
let bafap = And([true;false;true]) |> fired
let batap = And([true;true;true]) |> fired
let bofap = Or([false;false;false]) |> fired
let botap = Or([false;true;false]) |> fired
 
printfn "Your breakpoint here."
 


So what *is* the takeaway? It’s this: there may be entire classes of solutions that, under the OOP paradigm, get modeled poorly or not at all, for the no other reason than that the solution adds complexity and code beyond the worth of the model. Secondarily, the same can be for linguistic “ceremony,” which – for historical reasons – often emphasizes syntax at the expense of semantics.

-Neil

p.s. The astute reader will have already noticed that there is an even more succinct representation of the test in F#. It occurred to me as I was feeding Mr. Bun-bun his dinner:

 
let test = function
  | And(l) -> List.exists not l |> not
  | Or(l) -> List.exists id l 
 

And the definitions of "Test" and "fired" can be simplified to:

 
let (|Test|) = test 
 
let fired (Test(b)) = b
 

Which makes it plain that, in this oversimplified example, "fired" is just a complicated way of calling "test," but you get the picture...

Wednesday, April 28, 2010

F# vs. C# Proof-of-Concept at One Week

This being roughly a week into my large-scale F# proof-of-concept, I’d like to present what I feel are some of the benefits of F# over C# and vice versa. This includes “F#-style” in the sense that it encompasses multi-paradigm techniques that can be used in C#, but which are more naturally supported by the F# language (at least at this point).

Benefits of F# and F#-style over C#.

1) Fewer lines of source code.
2) Fewer classes.
3) Fewer functions.
4) Shallower hierarchy.
5) More direct modeling of the problem.
6) More efficient runtime IL (speed and probably space as well).
7) Constructs like easy operator overloading simplify testing and agile programming.

Benefits of C# over F# and F#-style.

1) Still getting used to the F# language and multi-paradigm programming.
2) VS2010 tools (e.g. auto-complete, refactoring) currently work better with C#.
3) Mechanics of C# projects (multiple sub-directories, etc.) more mature. (Although I do like the way F# harkens back to the older idea of source-code over project structure.)
4) Some conflict between F#-style/conventions and .NET library-style/conventions at this stage. (Minor issue only.)

So at least thus far, F# as a language is working out for me; most of the problems I have with F# are tool integration issues that will improve over time. I really, really like this language; programming is fun again!

(Lest any C# aficionados or C#-group members take offense, let me say that this is not intended to be a slight on C#. C# 4.0 is a very effective language and is itself growing into a multi-paradigm language. For many tasks, I think the choice of F# vs. C# will be a choice based on preference between equals.)

-Neil

Monday, April 26, 2010

Gap

Sorry for a bit of a gap in the posting. Blame Microsoft; VS2010 is full of new stuff and it's been a lot of fun playing around with it for the last couple of weeks!

One thing I've done is to begin my first large-scale project in F#; it's actually a proof-of-concept for some professional work I'm doing. It's going really well, and it has forced me to learn a lot of the nuts and bolts of putting together a large, maintainable project in F# as opposed to working mainly with isolated snippets and algorithms. Based on early analysis, I predict that it will benchmark faster than a C# version, and -- if I can get a handle on F# module and namespace practices -- it should be more maintainable. (The former due to the fact that the F# compiler provides very good optimization, and the latter due to the fact that the F# source is more succinct and more directly models the problem.)

I still have a few more hurdles to accomplish, including coming to grips with F#/Microsoft Office interaction, XML in F#, and WCF. But in the meantime, in an effort to keep this blog running, I'll cast about for some interesting things to post here.

Thanks again to the VS and F# team for making F# a reality in VS2010!

-Neil

Friday, April 16, 2010

VS2010 and a C# Aside

Like most people in the Microsoft-programming world, I've been in the midst of installing Visual Studio 2010 (I had to service pack my PC, etc.), and now I'm in the midst of experimenting with all the new features. Hopefully, the fact that F# is now included with the Studio will generate a lot of activity in the online F# world over the coming weeks.

In the meantime, here are a couple of C# articles that may be of interest to F# programmers:

Solving Combinatory Problems with LINQ

Using LINQ to solve puzzles

-Neil

Tuesday, June 30, 2009

Enumerators for Dependency Injection

A situation came up where I needed to select elements based on dependency injection. The elements were portions of a larger bitmap that were being used as tiles in a 2D graphics engine. Selection might be sequential, random, fixed, etc., but needed to be hidden from downstream processes. In particular, I needed to inject not the enumerators themselves, but enumerator factories.

At first I was going to use a custom interface. After some thought, however, I decided that the .NET IEnumerator<> interface fit the bill nicely. Technically an enumeration is some kind of ordered or unordered sequence from a collection. But a randomized sequence fits that bill, and it’s not too much of stretch to think of an infinitely looping sequence as an enumerator. (For example, think of the original collection as specifying the set of allowable items of an infinite sequence.)

So I came up the following helper functions:
static IEnumerator<TOutput> MakeEnumerator <TInput,TOutput,TState> (
TInput inputIn,
TState stateIn,
Func<TInput,TState,TState> funcMoveNext,
Func<TInput,TState,bool> funcMovedNextOk,
Func<TInput,TState,TOutput> funcCurrent)
{
while (true)
{
stateIn = funcMoveNext(inputIn,stateIn);

if (!funcMovedNextOk (inputIn,stateIn))
break;

yield return funcCurrent(inputIn,stateIn);
}
}


static Func<TInput,IEnumerator<TOutput>> MakeEnumeratorFunc <TInput,TOutput,TState> (
TState stateIn,
Func<TInput,TState,TState> funcMoveNext,
Func<TInput,TState,bool> funcMovedNextOk,
Func<TInput,TState,TOutput> funcCurrent)
{
return
(i)=> (
MakeEnumerator(
i,
stateIn,
funcMoveNext,
funcMovedNextOk,
funcCurrent));
}

The first helper is a generic enumerator builder that takes three functions and a state which control the enumeration. The functions transition from state to state, determine whether a transition has exhausted the enumerator, and select an enumerated item. (I separated the move next functionality and inverted its typical order because it makes things a lot more convenient.)

The second helper uses this first helper to build an enumerator factory function.

Below shows how this could be used to build an enumerator factory for canonical list enumeration. (You wouldn’t want to use these functions for this in a typical scenario; the traditional way would suffice there. They are mainly useful in dependency injection situations.)

Func<List<int>,IEnumerator<int>> xMakeEnumeratorFunc =
MakeEnumeratorFunc<List<int>,int,int>(
-1,
(i,s)=>(s+1),
(i,s)=>(s<i.Count),
(i,s)=>(i[s]));

List<int> xList = new List<int>() { 1, 3, 5, 7 };

IEnumerator<int> xEnumerator = xMakeEnumeratorFunc(xList);

// Inject xEnumerator here.

Fun, func, function!

(Tomorrow: I find a situation where a tradition boolean MoveNext is superior and post the overloaded functions.)

-Neil

Thursday, June 11, 2009

Enumerating Bits

OK, so the enumerating the set of subsets of non-zero bits is not a common task. But what about enumerating the set of non-zero bits in an integer? That’s something that tends to happen at least one or twice in any large project. Here’s how that can be done use a related function.

Given an integer (i), the least significant non-zero bit (b) can be found using this equation:

b = (i & -i)

(This is discussed as equation (37) in Donald Knuth’s The Art of Computer Programming, Volume 4, pre-fascicle 1A, page 8.)

It is easy to turn this into a loop which enumerates the bits in an integer:
while (xInteger>0)
{
int xBit = (xInteger & -xInteger);
xInteger &= ~xBit;
// Do something with xBit here.
}

(This is probably a case where one wouldn’t want to use a generic “yield return” enumerator, since if one is working at this level of detail, efficiency is probably the main concern.)

This can also be made to work in C# with unsigned integers by using various types of casting. But if efficiency is paramount, pay attention to the generated MSIL, since casting at some points generates more efficient code than does casting at other points.

Tests in release mode show that this construct is nearly four times faster in C# (.NET 3.5 version) than is shifting! But it looks arcane at first glance, so be sure to document the code well.

Tuesday, June 9, 2009

Power Set of a Bitmask

Here’s a cute trick for enumerating the power set of an integer bitmask. It’s based on equation (84) in Donald Knuth’s The Art of Computer Programming, Volume 4, pre-fascicle 1A, page 18, available in an "alpha test" version at:

http://www-cs-faculty.stanford.edu/~knuth/taocp.html

The idea is that, given a subset (x) of a mask (M) the next largest lexicographic subset (x') is:

x’ = (x – M) & M

Combined with the C# "yield return" statement, this allows a simple enumeration of the power set of a mask. You simply seed the subset with zero, and iterate until it is once again zero.

public static IEnumerable<int> PowerSet (
int maskIn)
{
int xSet = 0;

do
{
yield return xSet;
xSet = (xSet - maskIn) & maskIn;
}
while (xSet!=0);
}

For example, calling PowerSet(0x19) returns an enumerator which yields (in binary):

00000
00001
01000
01001
10000
10001
11000
11001


I can’t think of a specific use for it right off hand, but if a project uses enough bit manipulation, I’m sure something would arise.

Code Generator Oddity

The following is a exerpted example of my implementation of a well-known permutation algorithm. Note the code generation oddity flagged by the comment. This occurs in .NET 3.5 and Visual C# 2008. I leave the solution to the mystery to readers who like to disassemble and read MSIL, and think about what the JIT compiler may do to it.

protected static void Permute <TDatum> (
int beginIn,
int endIn,
TDatum[] dataIn,
Action<TDatum[]> dataActionIn)
where TDatum : IComparable
{
TDatum xDatumBegin;

if ((endIn-beginIn)<=1)
{
dataActionIn(dataIn);
}
else
{
Permute(
beginIn+1,
endIn,
dataIn,
dataActionIn);

for (int i=beginIn+1; i<endIn; i++)
{
xDatumBegin = dataIn[beginIn];

dataIn[beginIn] = dataIn[i];
dataIn[i] = xDatumBegin;

Permute(
beginIn+1,
endIn,
dataIn,
dataActionIn);

// Believe it or not, the compiler/loader
// will optimize the first block below
// to be almost 10% faster than the second.

#if thisIsFasterInDotNet
xDatumBegin = dataIn[beginIn];
dataIn[beginIn] = dataIn[i];
dataIn[i] = xDatumBegin;
#else
dataIn[i] = dataIn[beginIn];
dataIn[beginIn] = xDatumBegin;
#endif
}
}
}

Monday, April 27, 2009

LINQ

It would not take even a Dr. Watson to notice that this blog has been idle for over a year. It might, however, take a Sherlock Holmes to discern the reason why. So I will sum it up with a word:

LINQ

Shortly after the last post, I began playing around with the new version of Microsoft Visual Studio, which included LINQ and all the new lambda programming goodies. I realized they made obsolete many of the issues I had discussed in the previous entry.

Concurrently, I decided to port a professional expert system engine I wrote and maintain to the new version of Visual Studio. It was written mainly in C++, with .NET interface code in C#. As I went along, I found myself thinking: “Perhaps I should just re-write the whole engine from scratch, using the newest C# technology.”

And so I did. And interspersed with other projects, etc., it took the better part of nine months to complete the engine, and another couple of months to work out the kinks and get it hooked up to the external components (UI, etc.). It was a lot of fun, but it did interfere with my blogging, to say the least.

In retrospect, it was a good decision. I learned the new lambda elements of C# in a way that would have been tough using a less whole-hearted approach. I also learned possibly more than I ever wanted to know about C# generics, lol. I want to share some of the things I discovered in subsequent posts in this blog, but for now I’ll just share what I consider the most important discovery:

Every programmer, it seems, hates exception handling, and I am no exception. So, when I started the re-write, I decided that I would, for once in my exception handling life, be good and pay attention to it from the ground up. So I started my re-write by crafting a set of classes to let me handle and pass exceptions and returns. They were not intended to replace the existing .NET exception handling, but rather to work hand in glove with it. Also, I began a discipline of handing errors and exceptions fully and correctly in the code at the exact moment I was writing the code. No more “I’ll save error handling for a rainy day.” It took a few weeks, but it stuck; it’s now a habit and I don’t fear error handling any longer.

Best programming discovery I ever made.

Thursday, March 20, 2008

Hierarchical vs. Relational

Some Thoughts About Hierarchical vs. Relational Representation
Part 1 – Rationale

As a rule of thumb, I like to design things so that each instance has three possible representations: in-memory object, hierarchical (e.g. XML), and relational. This tends to work out well because these are the three media of exchange in most computer architecture. Thus, in-memory for quick manipulation, hierarchical for static storage and communication via remoting or clipboard, and relational for dynamic storage.

This tends to work seamlessly except in one particular area: referenced objects (i.e. indexed objects in relational systems). Which is unfortunate, because referenced objects are a key paradigm in most computer languages and are the backbone of relational databases. This problem of coordinating referenced objects comes up in virtually every large program or code library, from e-commerce databases, to 3D graphics systems, to spreadsheets, etc.

I’ve tried several generic solutions to this problem. Most worked, but most became unwieldy as the code grew and special cases were considered. Because of this, I’ve decided to accept the fact that generic solutions here are difficult, and decided that instead, hope lies in the design patterns approach.

So, over the course of the next few blog entries, I will be presenting a series of design patterns aimed at tackling this problem. I don’t presume to think that any of these techniques are novel. The point is to arrange a series of rules-of-thumb and ad-hoc solutions into a more coherent set of design patterns.

-Neil