Saturday, June 25, 2016

Returning an IEnumerable from a database

This is probably rather obvious, but... when returning an `IEnumerable` from a database, like the records from a table, don't do this:

using (var db = GetDatabase())
{
  return db.GetTable("Table1");
}

because it will throw an exception when trying to enumerate those records, since the database connection has already been disposed.

Don't do this either:

using (var db = GetDatabase())
{
  return db.GetTable("Table1").ToList();
}

because it will retrieve all records from the table, even if you only need a small subset.

A slightly better way is to do this:

using (var db = GetDatabase())
{
  foreach (var item in db.GetTable("Table1"))
    yield return item;
}

This way, the `Dispose` method doesn't get called until the enumeration is over and if you only `Take()` a limited number of records from the result, it won't load the whole table. On the other hand, if you only add `Where()` clauses to the result, it will still enumerate everything (the "where" doesn't get passed on to the database engine).

This is not perfect - it would be best if I could return an IQueryable so that additional filters get passed on to the database engine, but I haven't yet figured out how to do that.

Sunday, June 05, 2016

Aligning text

I needed to write some code in a console app to align what a user was saying, in case it was longer than a line (80 characters):

marcel: blah blah blah a lot of text that doesn't fit in 80 characters more blah
         blah blah
long_username: Contrary to popular belief, Lorem Ipsum is not simply random text
               . It has roots in a piece of classical Latin literature from 45 B
               C, making it over 2000 years old. Richard McClintock, a Latin pro
               fessor at Hampden-Sydney College in Virginia, looked up one of th

I wrote the code in two ways: an imperative, mutating style and a functional (recursive) style. I find the second one to be more elegant but since the entire project is something done as a hobby I don't much care about speed; your mileage might vary. I'm also quite certain the first method can be improved but… again, I don't need to do that so it doesn't get done.

As usual, use at your own risk, I don't care about copyrights, blah, blah. Oh, and the result will look bad if the text contains non-printable characters.

        private static string Align(string prefix, string text, int length = 80)
        {
            Debug.Assert(prefix != null);
            Debug.Assert(text != null);
            Debug.Assert(length > prefix.Length);

            var prefixLength = prefix.Length;

            var sb = new StringBuilder();

            do
            {
                var limit = Math.Min(text.Length, length - prefixLength);

                var current = text.Substring(0, limit);
                sb.Append(prefix + current);

                prefix = new string(' ', prefixLength);
                text = text.Substring(limit);
            } while (text != "");

            return sb.ToString();
        }

        private static string Align2(string prefix, string text, int length = 80)
        {
            Debug.Assert(prefix != null);
            Debug.Assert(text != null);
            Debug.Assert(length > prefix.Length);

            var all = prefix + text;

            return all.Length <= length
                ? all
                : all.Substring(0, length) +
                  Align2(new string(' ', prefix.Length), all.Substring(length), length);
        }

Hmm... I think this would be an interesting exercise if I wanted to hire programmers.

Math is a game

Math is a game, an arbitrary set of symbols and rules. The weird part, the part that always surprises me, is that it's relevant to the real world.

Here's an example: we'll start with just two symbols, Yin and Yang. (Replace those with black and white, circle and square, X and Y… whichever two symbols you prefer.) What can we do with them?

Well, the simplest thing we can do is transform one into the other:

Yin → Yang; Yang → Yin

We'll call this transformation "mirroring" and denote it with the letter "M".

What about combining two symbols? We have a number of possibilities:

A) Yin, Yang → Yin; Yang, Yin → Yin; Yin, Yin → Yin; Yang, Yang → Yin

This is rather boring… no matter what we start with, we obtain an Yin symbol. Nevertheless, let's continue.

B) The opposite of A: Yin, Yang → Yang; Yang, Yin → Yang; Yin, Yin → Yang; Yang, Yang → Yang. Still boring.

C) Yin, Yang → Yin; Yang, Yin → Yin; Yin, Yin → Yin; Yang, Yang → Yang

Ok, so this is a bit more interesting: this combination still overwhelmingly favors the Yin symbol, but at least once in a while we get back an Yang. For completion, we'll also write down its opposite:

D) Yin, Yang → Yang; Yang, Yin → Yang; Yin, Yin → Yang; Yang, Yang → Yin

The last two combinations give us an equal distribution of the results:

E) Yin, Yang → Yin; Yang, Yin → Yin; Yin, Yin → Yang; Yang, Yang → Yang

F) Yin, Yang → Yang; Yang, Yin → Yang; Yin, Yin → Yin; Yang, Yang → Yin

I'll summarize the A..F combinations in a table:

1st 2nd A B C D E F
Yin Yang Yin Yang Yin Yang Yin Yang
Yang Yin Yin Yang Yin Yang Yin Yang
Yin Yin Yin Yang Yin Yang Yang Yin
Yang Yang Yin Yang Yang Yin Yang Yin

So, what was the point of all this? In itself, nothing much. We can imagine that two kids might alternate playing this game, where one of them writes symbols and the other one combines them to obtain the result, and the one with the most correct results wins. It doesn't really matter: the interesting part is that we just re-invented Boolean logic. The Yin and Yang symbols are 0 and 1 (or true and false) and the transformations are the well-known Boolean operators: and, or, xor, equ and finally not for what we called "mirroring" (I've ignored the "boring" A and B). Given that Boolean logic is used by all computers, this is quite amazing - what looked like rather pointless playing with two symbols picked at random proved to be hugely important.