Matt's Mind

Wednesday, September 29, 2004

I love (to chuckle at) Win32

This is a work of beauty (taken from this article by Raymond Chen). The code below is handling popup menu selections in order to show help text in the status bar (actually the window title in the example).
void OnMenuSelect(HWND hwnd, HMENU hmenu,

int item, HMENU hmenuPopup, UINT flags)
{
if (g_pcm && item >= SCRATCH_QCM_FIRST &&
item <= SCRATCH_QCM_LAST)
{
WCHAR szBuf[MAX_PATH];

if (FAILED(IContextMenu_GetCommandString(g_pcm,
item - SCRATCH_QCM_FIRST,
GCS_HELPTEXTW, NULL, szBuf, MAX_PATH)))
{
lstrcpynW(szBuf, L"No help available.", MAX_PATH);
}
SetWindowTextW(hwnd, szBuf);
}
}
Ah, so wonderfully readable and obvious (see Raymond's post for more crunchy C/Win32 goodness). No wonder people actually like VB given that this sort of madness is the alternative. And this is from article 6 in a series of how to manage popup menus in Windows. Eeeek!

Tuesday, September 28, 2004

Nice!

This language called Nice is one of the few new languages I've seen recently that really looks like next step on from Java. It adds a lot of expressive, functional capabilities that I've wanted for a while, while not gratuitously inventing its own alien syntax.

One of the really neat things are multi-methods, which might sound dull, but actually address a real problem I've had in Java for a while: how to implement extensible "utility" methods that aren't logically part of a class. For exanple in Java you might do this (taken from this tutorial wiki):
package my.package;


import geometry.*;

class Tools
{
static boolean overlap(Shape s1, Shape s2)
{
if (s1 instanceof Rectangle && s2 instanceof Rectangle)
{
...
// return the result in this case
}
throw new Error("Case not supported: " + s1.getClass() + " and " + s2,getClass());
}
}
But in Nice you can do this:
package my.package;


import geometry;

boolean overlap(Shape s1, Shape s2);

overlap(Rectangle s1, Rectangle s2)
{
// Here s1 and s2 are both rectangles. We don't need to use instanceof or cast.
...
// return the result
}
Which is far neater and extensible: you can add new sorts of Shape and new versions of overlap (), which wouldn't be possible in the Java version.

Java generics

This article by one of the sw engineers at Google about the reasons behind the decision to use the "erasure" approach for Java generics is very enlightening. The purist in me derides the limitations imposed by the approach, which are mainly due to the fact that the generic type parameters are not available at runtime, only at compile-time.

The realist in me understands that, although pure generics might be prettier, the massive Java codebase demands a way to migrate smoothly between non-generic and generic worlds, what he terms "Migration Compatibility". This allows a company to start shipping a generified version of their library that is fully forwards and backwards compatible with both environments, thus not forcing clients one step up the chain to go all generic or all non-generic - they can migrate as they write new code and leave old code intact.

Update: this article by Bruce Eckel responds to these arguments. Bear in mind that Bruce is from the dynamic typing camp.

Wednesday, September 08, 2004

More API craziness

This is how you make a String from an array of bytes in .NET:
System.Text.Encoding encoding = System.Text.Encoding.UTF8;

return encoding.GetString (buffer);
This is how you do it in Java:
return new String (buffer, "UTF-8");
If you have an array of bytes that you want to stringify, then you'll likely go straight to the String class to see what kinds of things it can do with byte arrays. In .NET you need to find your way to System.Text.Encoding and then work it out from there.

(I really, really dislike .NET's "always capitalise everything whether it's a package, class, constant or variable" naming convention. What a waste of an alphabet).

More on dynamically typed languages

Check this Python API document for a mail-processing library:
class UnixMailbox( fp[, factory]) Access to a classic Unix-style mailbox, where all messages are contained in a single file and separated by "From "(a.k.a. "From_") lines. The file object fp points to the mailbox file. The optional factory parameter is a callable that should create new message objects. factory is called with one argument, fp by the next() method of the mailbox object. The default is the rfc822.Message class (see the rfc822 module - and the note below).
This is a classic example of why dynamic typing makes it harder to understand an API. So you need a "fp" to create a UnixMailbox instance. Que? "The file object fp points to the mailbox file" - oh, I see, that makes it much clearer. Now I can go and grep for "file" and see that class might actually do the job here. Is it a file, filename, something that implements open () and read (), any of the above?

With a statically typed language it would be "class UnixMailbox (File file)", with a link to the File class so I can work out how I can make one that fits.