(sort of) first class classes in C#

2010-08-10

I find myself writing some C# code while still thinking in Python. One thing in particular caught me out … it seems, at first, that C# doesn’t have first class classes. This is annoying, because I’d started writing some device driver classes where each class is a type of device, and instances represent the individual devices themselves. And I wanted to construct a list of these classes, and call a “probe” classmethod on each of them to ask the class to go search out any devices which were available. In Python, this would look like:


device_classes = (FooDevice, BarDevice, BazDevice)

for device_class in device_classes:
device_class.probe()

See? The classes are being treated just like any other variable, because they are, they’re just instances of type ‘classobj’ . But the equivalent doesn’t work in C# — doing this:


Type[] DeviceClasses = {
FooDevice,
BarDevice,
BazDevice
};

… complains that “‘FooDevice’ is a ‘type’ but is used like a ‘variable’”. At first it seemed that C# didn’t have first class classes, and indeed a few web searches came up empty handed.

Thankfully after a bit more exploration it turns out that all that is needed is some syntactic nastiness … namely, typeof(), GetMethod() and Invoke() (Passing “null” to Invoke works for static methods).


Type[] DeviceClasses = {
typeof(FooDevice),
typeof(BarDevice),
typeof(BazDevice)
};

foreach (Type dct in DeviceClasses) {
dct.GetMethod("Probe").Invoke(null, new object[] {} );
}

Now, quite why a shiny new programming language has to get saddled with such godawful syntax is a bit beyond me, but so it goes.

As always, this is lovingly documented in MSDN, in such a way that the answer is clear so long as you already know what you’re looking for.

(As a bonus, yes, you can use reflection to find the list of Devices in the first place. It just wasn’t all that relevant to this example)


NonTemplate

2010-04-30

It is rather sketchy still, but I’ve just put up a little idea about a way to avoid doing template languages at all, and
embedding HTML into Python code directly instead.

It is called NonTemplate. Let me know what you think!

UPDATE: Some vague performance figures, using the same very simple benchmark as the previous template language performance comparison posts.

These figures are running on Python 2.6.5, on a linux laptop (x64) with output to /dev/null …

print: 1.612
Mako: 1.756
Jinja: 10.803
nontemplate: 18.198
django: 42.212
SimpleTAL: 59.024
genshi: 81.460

… mako is very very clearly the winner here … its code generation is head-and-shoulders above the rest, producing pretty much
exactly the same code as you’d get if you wrote a whole lot of “print” statements yourself. Nontemplate is stuck in the middle … unfortunately, all the ‘with’ shenanigans turns out to be pretty slow. On the other hand, it is still a lot quicker than Django templates, SimpleTAL or Genshi, and a lot smaller than any of them, so I guess it is not all bad news.


SyntaxError: keyword argument repeated

2009-09-22

This one is amusing … the case of the mysterious syntax error … turns out that repeated keyword arguments (kwargs) were illegal in python 2.4, ignored in python 2.5 and illegal again in python 2.6. This means that if some have crept into your codebase, you’ve now got a handful of syntax errors!

For example, here’s test.py:

    def foo(**kwargs):
        for k, v in kwargs.iteritems():
            print "%s: %s" % (k, v)

    foo(a = 1, b = 2, a = 3)

And here’s what happens when you run it under 2.4, 2.5 and 2.6:

    nick@pluto:~/tmp$ python2.4 test.py
      File "test.py", line 5
        foo(a = 1, b = 2, a = 3)
    SyntaxError: duplicate keyword argument
    nick@pluto:~/tmp$ python2.5 test.py
    a: 3
    b: 2
    nick@pluto:~/tmp$ python2.6 test.py
      File "test.py", line 5
        foo(a = 1, b = 2, a = 3)
    SyntaxError: keyword argument repeated

How could this creep in? Most likely through revision control mergers. Function calls with lots of kwargs are often laid out like:

    foo(
        kwarg_with_a_long_name=1,
        another_self_documenting_flag=False,
    )

Alice adds a kwarg for yadda="yadda yadda", at the start on the kwargs list, before kwarg_with_a_long_name. So does Bob, but Bob adds it at the end. The revision control system will happily merge these two changes without conflicts as:

    foo(
        yadda="yadda yadda",
        kwarg_with_a_long_name=1,
        another_self_documenting_flag=False,
        yadda="yadda yadda",
    )

And under python 2.5, neither Alice or Bob are likely to notice … after all, yadda=”yadda yadda” just as they intended.

But when the underlying system is upgraded to python 2.6, a mysterious “SyntaxError: keyword argument repeated” appears.


Multiple Inequalities in Google AppEngine

2009-08-11

So I’m playing around with Google AppEngine (still!) trying to put together some kind of sensible use for it. AppEngine is neat-O, but it is also quite limited in what it can and can’t do. One of the most glaring problems (for my toy app) is the datastore query API, which has various restrictions, including:

Inequality Filters Are Allowed On One Property Only

Now this is pretty obviously an efficiency measure: retrieving on inequalities involves iterating along one index, and the datastore isn’t in the business of picking which one to iterate along. But its also really annoying if you actually want to do something which needs multiple inequalities.
Read the rest of this entry »


Templates Fugit 3

2009-07-29

I’m still messing around with template languages … I’ve added a couple of new ones and here’s the revised leader board.  I tried adding ClearSilver for Perl & Python but I couldn’t get either of those to work …  pity, its an interesting approach.  As with the previous posts this is time in seconds for  1000 tables of 100 rows by 10 columns each, not counting template compilation time.  The 200x difference in performance is what makes it interesting:
Read the rest of this entry »


Templates Fugit 2: Serpents vs. Camels

2009-06-25

Why should Perl have all the fun?  Lets do the same thing but in Python, comparing Mako, Jinja and SimpleTAL: Read the rest of this entry »