Pragmas, Tags, Attributes, Annotations
Return to home page
Comments Loading...
2007-02-26

The humble Pragma has had a hard life so far. It exists in only one Smalltalk - VisualWorks - and even there it has suffered much scorn since its inception. I must confess that when I first came in to contact with this strange <syntax> I was most puzzled and curious at the same time. I felt that perhaps someone had made a terrible mistake and that somehow my beloved language had been soiled.

It seems I was not alone, but I knew from experience that you should always try out new ideas. So, I used Pragmas in WithStyle to allow the extension of XML initialization behavior. It idea was simple enough - when we parse the XML but before we render it, we may want to interpret what the XML means in certain ways. Example: an <a> tag acts as a link, a <style> tag adds new CSS to the page, a <link> tag downloads other resources, so on and so forth.

This technique, however, did not pan out the way I had hoped. It was slow, cumbersome and prone to error. It seems that Pragmas have their place and it is not a ubiquitous as I had first hoped. In WithStyle 4 I have removed that particular use of Pragmas. At that point I thought that perhaps Pragmas weren't so great after all.

Since then, I have constantly thought about them and how they were there.. how useful they were with menu extensions and toolbar extensions. It was clear they were useful, so why weren't they useful when I used them? I decided to try another experiment. What if I used them to define servlet interfaces and server listeners? Would that work well?

It turns out that yes, it does work well. Pragmas are useful for all kinds of jobs and in fact they would still be useful in XML initialization too - if they were faster. Not just that though, the programming model of the humble Pragma is such that you find yourself writing procedural code to deal with them.

It becomes clear that we are missing an object oriented pattern when we see code everywhere that interprets the arguments of Pragmas to achieve an outcome. Often this outcome is to process the arguments, or to confirm the existence of the Pragma or better yet, build objects out of the Pragma. We will come back to this later.

For now, I'd like to discuss the naming of Pragmas. Perhaps this is where we can trace back the roots of peoples distaste for Pragmas and may be even fix that with some healthy examples of how to use them and what they're for.

When we dig in to the guts of what is going on, we discover that when you add a Pragma to your method, instead of getting a CompiledMethod, we end up with an AnnotatedMethod instead. This is a subclass of CompiledMethod and it does little but add a new instance variable called attributes. When we start digging around in the RBParser (although this is not the parser used to compile the methods, it is the parser used while highlighting your code as you write it) we discover that the <> syntax is marked as a Tag. Finally, the object that gets placed in the attributes collection on an AnnotatedMethod is a Pragma.

We have a problem. We now have four terms to describe the same 'thing'. Pragma, Attribute, Annotation and Tag. Why do we have so many labels for it? Well, tag was the inception of the refactoring browser guys - why they chose to pick a new terminology is any ones guess. The oldest term in the image is the AnnotatedMethod with its attributes. It existed for UserPrimitives and MarkedMethods long before Pragmas arrived on the scene. So that breaks it down to Annotation and Attribute. Attribute is clearly too generic, so that really leaves Annotation.

But what a dreadful name - Annotation, which is generally reserved for the scribblings along the margin or at the bottom of your diary. "a critical or explanatory note". So it's a note then. How about we examine the other two choices a little more closely. Pragma, for example, is a word specially reserved for computing: "A standardised form of comment which has meaning to a compiler". This may have been true of pragmas such as <C: void main(void)> and <primitive: 123>, but it is not true of any other pragma in a Smalltalk image.

Those Pragmas are in fact meaningful not to the compiler, but to the developer. They are generally used to Tag a method in some fashion and execute behavior based on that tag. Now tag is a good word for what we're doing here. We're adding some more information to our method that someone can act on. If we review how we use Pragmas, we can see that tags fit pretty well:

They aren't compiler hints or instructions, they're not explanatory notes, they are tags in the trust sense of the word - "for attaching by one end to something as a mark or label". Okay, so it doesn't fit that well, but it's a much better fit than the other options listed above. It also happens to be travis's initials - but he claims that there's no bias toward it because of that ;)

Shortly, I'm going to post up an analysis of Pragmas and their uses in VisualWorks, hopefully to shed some light on why they are so great and why you should love them and not hate them.