waffle

Developers

This week has been very interesting so far, and it’s been interesting almost solely because of PDC. (Microsoft’s Professional Developers Conference. Yes, Microsoft.)

C# 4.0 has on the surface very few improvements, but they are deep. There’s our old friend dynamic, using which the compiler types the object as object and defers any further method invocation validation until run-time. (By the way, typeof(dynamic) is invalid, dynamic obj /* .. */; obj.GetType(); will return the run-time type, and in the generated IL, the declarations look like [DynamicAttribute] object.) Work is being done here to unify all of the run-time invocation methods in the different APIs.

There’s optional and named parameters. Optional parameters are more or less functionally a noop in terms of shall we say “turing-completeness”, but the existing technology you’d have to use would be a cartesian product of overloads for all optional parameters, and it falls down if you have two or more parameters of the same type, which is where named parameters come in. They’re not selectors, but if you squint just right, though… foo(1, bar:42, baz:8)… isn’t that MacRuby?

There’s co/ntravariance, which means that you can treat a list of strings as a list of objects in certain circumstances without spending valuable time casting. And there’s lots of COM interop patches, if you spend all your time generating enthralling Powerpoint presentations on realizing synergies and leveraging n-tier paradigms.

What makes C# 4.0 interesting is mining those features for hidden potential. Keen eyes may have noticed that you can now write duck typing code and generally delay binding in C#. Well, no. Here, let me show you:

class Example {
    class Animal { }
    class Dog : Animal { }
    class Giraffe : Animal { }

    static Random sharedRandom = new Random();

    static Animal FetchMeAnAnimal() {
        return (sharedRandom.Next(0, 2) == 1 ?
            (Animal)new Dog() : (Animal)new Giraffe());
    }    

    static bool ReachHigh(Animal anyAnimal) {
        return false; 
        // on average, animals aren't that tall!
    }

    static bool ReachHigh(Giraffe aGiraffe) {
        return true;
        // giraffes, though... they're tall.
    }


    static void Main() {
        Animal fetchedAnimal = FetchMeAnAnimal();
        bool reached = ReachHigh(fetchedAnimal);
        // reached will always be false, even if
        // the animal ended up being a giraffe

        var varAnimal = FetchMeAnAnimal();
        reached = ReachHigh(fetchedAnimal);
        // reached will *still* always be false; the 
        // compiler is just inferring "Animal" for you

        // try 1
        dynamic dynamicAnimal = FetchMeAnAnimal();
        reached = ReachHigh(dynamicAnimal);
        // WON'T WORK: you're calling a method taking a 
        // statically typed parameter, and there's no 
        // conversion. compile error.

        // try 2
        reached = ReachHigh((Animal)dynamicAnimal);
        // WON'T WORK EITHER: now it's a static type,
        // but since you're casting it down to an Animal 
        // the compiler will make sure the Animal-taking 
        // overload is called. 
    }
}

Actually, there’s no way that I can find that has reached be false when the dog’s fetched but true when the giraffe’s fetched, save for a sane implementation of the above problem. The problem wasn’t designed to be sane, but to highlight this problem. This leaves precious little duck typing ability in the language – what dynamic properties or methods you can exploit rely on foregoing static typing entirely and using dynamic at every step of the chain. If you were holding out for this, you were looking for the wrong language – at least you can take solace in being able to define the hilarious method static dynamic Foo(), though.

What has me really interested in PDC is the relatively open structure, though. Talks are available to watch and download on Channel 9 for free without registration, and I downloaded the Visual Studio 2010+.NET 4.0 virtual machine and tested every line of code written in this post. This is definitely something I wish Apple aped. Not everyone can go to WWDC (especially sold-out ones), and I’d like to see the sessions, even for a modest sum.

One of the talks is The Future of C# where Anders Hejlsberg goes into detail on the new C# features. It’s a well-done talk. Anders acknowledges the “hack” of statically typing some objects as being dynamic and draws laughters, and thanks to the dynamism and interop features rewrites some JavaScript in a HTML page hosting a Silverlight program in C#.

The best oohs and aahs come at the very end, though, where Anders demos the upcoming (post-2010, sadly) C# C# compiler — that is, a C# compiler that’s also written in C# — which can be used as a service. Quickly, a Read-Evaluate-Print shell (”C#>”) is assembled and is made to do shell-like things as everything entered is compiled and appended to the running assembly.

Anders touches upon something I think most people were wondering about at that point. With all these dynamic features, it still won’t integrate very well, and we can’t really do metaprogramming at the level that we might like to, which is one of the major points of dynamic languages. The C# compiler service classes will be able to return the output as an abstract syntax tree which you can remodel at will, making refactoring and (premature?) optimization possible. That something like this exists and is pushed even by C#’s creator and architect stands as a great credit to the .NET platform and to Microsoft. It is probably the most exciting thing mentioned at PDC in the same sentence as “software” and “service”. This kind of thing is where we’ll need to go in the future.

Moreover, I advise that the iPhone software platform must be opened.

Packed

Spot the error:

uuid_t uuid_now;
uuid_generate(uuid_now);
char *uuid_cstr;
uuid_unparse_lower(uuid_now,uuid_cstr);

The error is that uuid_cstr is not initialized. I was writing the original code up to uuid_unparse_lower by hand but then I got lazy and googled, and found that yeah, it was done that way. What I missed was that in every instance this was shown, they were using char uuid_cstr[37] and were thus actually initializing their string^Wchar array — 36 chars + the null — while I was just declaring a pointer.

This all boils down to that packing up services worked great in ThisService, provided you were lucky and the program ran in pre-zeroed space, or the application wouldn’t, when this was turned into a string seconds later, find the null string terminator and crash and burn horribly.

Whoops.

I fixed this (by also forgoing it for CFUUID) and, humble from experience and eager to shoot down anything else pre-emptively, ran and reran the wonderful clang static analysis program — earlier in the week that just ended, I proposed the name “clunk” but am now coming around to “mechanical Hosey” as well — on the source code for about an hour until most kinks were worked out. Then I updated some web pages in which process is still as embarrassingly manual as is the “memory management” in most Objective-C applications (unless you write only 10.5 applications), and I uploaded a new version and slapped “2.0.2″ to the side of it.

You are welcome to upgrade.

Moreover, I advise that the iPhone software platform must be opened.

Chill

I’ve just about had it with forced, contrived, smile-at-all-costs optimism in my lifetime already. The next 130 or so days are going to be crap weatherwise. It’s going to be dark and cold here, and it’s going to affect the moods of everyone else, which means it’s going to affect me too because that’s how people work.

So about that, why would I want to force this destructive attitude on myself? Here’s my thinking: to each their own, but out of all these things, I can control one thing directly and that’s how I feel about things. I can be allured to grovel in the general down of this time of year… or I can take a slightly more relaxed attitude. What I’m going to do isn’t going to crap itself out by default, and despite the impending arrival of frozen water in peculiar molecular arrangements (though I was born in the midst of it, I’m not a winter person), I’m still pretty happy.

Despite what the the-corners-of-my-mouth-meet-in-the-back-of-my-head drones might tell you, the world doesn’t love you and everything is not going to be alright in the long run. (Nothing gets me more depressed than that brand of policy optimism.) Don’t smile if you don’t feel like smiling, but don’t mindlessly assume failure either. Just a kindly word from your author, who isn’t going to deprecate himself in this sentence or the next.

Moreover, I advise that the iPhone software platform must be opened.

Ruby Wednesday

Cocoa knocked on my door. I opened, and it stepped in. It scratched its feet against the carpet and glanced down briefly. “Look…”, it went. “I’m sorry about the whole ‘C-based’ thing. Didn’t want to insist, but it was all I knew. You never wanted that, did you?” I nodded. “Here.” It handed me a package. “This is early stuff, alright? More like the way you wanted to do it. I mean, there’s no good autocompletion…” It flashed a smile, but something was different. “You noticed. Removed my braces… I think this is something you’re going to like.”

I’ve been trying MacRuby for the past few days — it’s Ruby, draped on top of the Objective-C runtime, so every Ruby object is secretly an NSObject, and everything else works just as you’d think it would. About twenty minutes in, to the extent that I love programming, I loved programming in MacRuby. It feels like the prelude to this post really happened. Everything I love about Ruby is still there. Everything I love about Cocoa is still there. I looked up about three sentences of documentation for reference. Everything just worked.

Well, mostly. MacRuby is a very young project, and it’s more ambitious than the existing bridges. (I’m not even sure whether it’s a bridge anymore.) It seems like the more code I write the more stubs I fall over. I can’t require 'json'. I can’t use variadic functions (and the method call syntax makes me wonder how variadic methods will work). Bytestrings are a mess and won’t work well at all — you’ve just got a string all of a sudden that will work just fine unless you want to get at its length or individual characters, or concatenate it somewhere unfortunate.

But these are details. If I had a penny for every time I’ve fell over some sort of project that was really solid in its implementation, but that I just didn’t like or couldn’t work in, I’d have so many pennies, I’d fill — oh, nevermind. MacRuby is the opposite of this in that it gets the fundamentals shamelessly right from the beginning. There’s still culture shock. The Ruby and Cocoa worlds are colliding, just as I thought. But in the meantime, I find I have to unlearn how bridging traditionally works in many aspects.

I wouldn’t switch over production code to this. I can’t. I’ve tried, as you might have imagined. It just doesn’t work right now. But the model works. As good as Objective-C is, I can certainly stand to see this improve over time. It’s brilliant.

Moreover, I advise that the iPhone software platform must be opened.

Older posts »