Fat is an economic issue 11
Terry Pratchett once observed that a character of his was anorexic because every time they looked in a mirror, they saw a fat person. By that measure, I’m anorexic, though I tend to avoid mirrors. By more objective measures, I’m morbidly obese – 6’ tall, 346 pounds; the Body Mass Index calculation is never going to give a good number.
To listen to some sections of the press, I might as well be public enemy number one. A drain on the public purse, a morally bankrupt insult to the eye of the right thinking, Daily Mail reading healthy public. Apparently, I have the self control of an incontinent puppy and spend my time sat on my arse in front of the TV or looking at child porn on the internet, constantly stuffing my face with lard and chocolate.
Mmm… lard and chocolate…
Now, everyone’s entitled to their opinions of the morality of others. Catch me on another day, and I can rant for ages about the ugliness of the way diet and beauty industries stoke insecurities to sell product. Today I want to talk about the cost issue.
Fat people aren’t cheap to keep – we tend to die younger, and in the process of our dying we cost a lot of money. But dying can be an expensive business and however we go, we all do sooner or later. Fat people’s healthcare costs may well be higher than those of healthy people of the same age, but those healthy people could end up waiting ‘til they are 80 before dying of something horribly expensive like cancer, or Alzheimer’s.
When you add up the net lifetime healthcare costs of the average healthy person, and those of the average obese person, the healthy person costs more.
This is analogous to the “Long Tail” idea – the idea that the long tail of low sales of ‘specialist’ books/records/services adds up to being of greater value than the total sales of the top 100 or whatever. Obvious when you think about it, but running counter to traditional thinking in this area.
We’re really good at spotting the big things, but rather less good at spotting the slow accretion of small things. Each drop of water that falls from a stalactite to a stalagmite doesn’t appear to contribute anything. Nevertheless, the stalactite and stalagmite got there somehow.
I find this knowledge rather heartening. Okay, so as a fat git with diabetes, I’m likely to die young, but that’s my business. The pernicious idea that the broader population of tax payers is somehow suffering because of me and that because of that I should be denied access to health care isn’t just morally repugnant, it’s economically illiterate.
References
Lifetime Medical Costs of Obesity: Prevention No Cure for Increasing Health Expenditure from PLoS medicine. The paper describes a mathematical model rather than something which does the arithmetic on a real population, so it’s only as good as the assumptions, but it does seem compelling that the driver for high total healthcare costs over a lifetime is the length of that life. But, as I fat git, I might be expected to say that. Ho hum.
Code is data, and it always has been 3
I’m just back from the first Scotland on Rails conference, and a jolly fine conference it was too. Much kudos is due to Alan, Graeme, Abdel and Paul. It was hard to believe that this was the first conference these guys have run and I think all my fellow delegates hope it won’t be the last. As I said in the Pub on Saturday night, I’d had a talk proposal knocked back and, in that situation, it’s terribly easy to find yourself sitting in a session thinking “Bloody hell, my talk would have been better than this!”, but not at this conference.
A phrase that cropped up a couple of times was the old saw that “Data == Code” – it’s very hard to avoid the idea once you start talking about code generation or Domain Specific Pidgins, parsing… I first came across the idea in The Structure And Interpretation of Computer Programs where it’s elegantly phrased as “Data is just dumb code, and code is just smart data”. Traditionally, the idea seems to be attributed to John McCarthy, the inventor of Lisp. But it’s older than that. Way older than that. The idea is actually older than Computer Science. It lies at the core of Turing’s original paper On Computable Numbers, with an Application to the Entscheidungsproblem in which invents computer science on the way to proving that it’s impossible to decide algorithmically whether a given statement of arithmetic is true or false.
In the course of the paper, Turing posits what has become known as the Halting Problem:
Given a description of a program and a finite input, decide whether the program finishes running or will run forever, given that input.
Turing’s proof runs something like this:
Suppose we have a subroutine halts?(code,data) which solves the halting problem. Let’s use that to write something like:
def counter_example(code)
if halts? code, code
for (;;)
end
else
return
end
end
counter_example(File.read(STDIN))and ask the question “What happens when we run counter_example.rb < counter_example.rb”? If halts? reckons that counter_example would halt, given itself as input, then counter example will enter an infinite loop, but if halts? reckon that it would enter an infinite loop, then it would halt. Which is a contradiction. Which means that there can be no subroutine halts?, which means that maths is hard enough to be interesting and occasionally undecidable.
Look at how the proof works – it’s built around the idea that code can be treated as data. In fact, you could say that the Turing Machine looks like it does because Turing was working backwards from this core idea to describe a sufficiently powerful machine that could obviously treat it’s own description as data. Certainly when you compare the clarity of his proof that the halting problem is undecidable (given the idea of the universal Turing machine) with the contortions required to make mathematics swallow its own tail in similar fashion so that Gödel could prove his Incompleteness Theorem.
So, if you want to know who the idea that code is data is due to, the answer (as is so often the case in our field) is Turing.
Postscript
Incidentally, Turing is also responsible for the first ever bug – his original implementation of a Universal Turing Machine has a couple, one of which is probably a dumb typo (which even I could spot when I read the paper). Another is more subtle, but still fixable. Somewhat delightfully, a young grad student, (Donald W Davies, who invented packet switching) spotted these bugs and told Turing:
I … found a number of quite bad programming errors, in effect, in the specification of the machine that he had written down, and I had worked out how to overcome these. I went along to tell him and I was rather cock-a-hoop … I thought he would say ‘Oh fine, I’ll send along an addendum. But in fact he was very annoyed, and pointed out furiously that really it didn’t matter, the thing was right in principle, and altogether I found him extremely touchy on this subject.
Nearly fifty years later Davies wrote and published a debugged version of the code, which you can find in The Essential Turing. One lesson to draw from the above is that getting annoyed at people pointing out trivial bugs in example code is also at least as old as computer science. Rather splendidly, there’s also a story of the chap who wrote the first ever assembler getting a serious telling off from Turing because the computer’s time was too valuable to waste it on converting symbols into machine code when humans were perfectly capable of doing it themselves. Who knows, maybe Turing’s contention was actually true back in the days of the Manchester Baby…
Tragedy
There’s always a moment, in a perfect tragedy, where you dare to hope that maybe the heroes are going to break the surface tension of the plot and escape. That perfect moment in Romeo and Juliet where, no matter how often you’ve seen it, you hope that this time, Juliet’s message will reach Romeo. Or, when watching Cruel Intentions, you find yourself hoping that the writers have managed to wangle a happy ending.
It never happens of course, and we’d be disappointed if it did. We are taken to the critical point, when everything seems possible, when the characters are pushed to their utmost… and fail. Give me the life and death struggles of two teenagers for whom love is everything and life isn’t worth living without it over the pat solutions of the Dream, or give me “Fortinbras, knee deep in Danes” over the cross dressing, weddings and cruel taunts of Twelfth Night. (Not that I don’t enjoy the comedies).
What brought this one?
Why am I musing on tragedy instead of code?
The explanation is simple: I just watched the last ever episode of The Wire.
If you follow the show yourself, nothing more is needed. If you don’t, why not? Okay, so if you’re in the UK you’re reduced to paying the Murdoch tax, buying the DVDs or watching through Bittorrent (and only Bittorrent is up to date), but you should. All five seasons of The Wire add up to being the best thing I’ve ever seen on television. It’s impossible to describe how good it is without misrepresenting the whole. It’s the kind of campaigning documentary fiction which would make Dickens or Mrs Gaskell proud. It’s a sprawling epic with a huge cast of fascinating and flawed characters. It’s the story of how a cop destroys his career, a junky kicks his habit, a school system fails its pupils, politicians fail their constituents, a newspaper fails its readers and how a policy of prohibition fails a country.
Prohibition and its consequences are shot through the fabric of The Wire. It’s easy to see how drugs destroy addicts. Easy (for liberal old me at least) to see how the money spent in the War on Drugs could be spent more effectively. What’s not so easy, and what The Wire does so well, is to show how “the game” destroys generation after generation of the best and brightest of the urban poor too. Why bother working to get to college, or getting a regular job when selling drugs is so easy and so profitable? If you’re going to jail for selling the stuff in the first place, why scruple to put a bullet in the head of a business rival, witness, or some mope who calls you a coward? How many “mute, inglorious Miltons” end up dead and decaying in a walled up vacant, or stuck behind the barbed wire of the state pen serving out their natural lives with no hope of parole?
And what does putting them away achieve? For every small victory, we’re shown a corresponding fall. New characters slot into the rôles they have vacated and the cycle begins again. It’s a perfect tragedy – the game is still rigged and only the players change. The gods are unmoved by the struggles of poor mortals, the lawyers get richer, incompetence is rewarded and money is siphoned away from the streets into the pockets of rich white men who already have plenty.
Welcome to Baltimore. Have a nice day.
Javascript scoping makes my head hurt 13
Who came up with the javascript scoping rules? What were they smoking. Here’s some Noddy Perl that demonstrates what I’m on about:
my @subs;
for my $i (0..4) {
push @subs, sub { $i }
}
print $subs[0]->(); # => 0;Here’s the equivalent (or what I thought should be the equivalent) in Javscript:
var subs = [];
for (var i in [0,1,2,3,4]) {
subs[i] = function () {
return i;
}
}
alert subs[0]() // => 4What’s going on? In Perl, $i is scoped to the for block. Essentially, each time through the loop, a new variable is created, so the generated closures all refer to different $is. In Javascript, i is scoped to the for loop’s containing function. Each of the generated closures refer to the same i. Which means that, to get the same effect as the perl code, you must write:
var subs = [];
for (var shared_i in [0,1,2,3,4]) {
(function (i) {
subs[i] = function () {
return i;
};
})(shared_i);
}
subs[0]() // => 0Dodgy Ruby scoping
I had initially planned to write the example “How it should work” code in Ruby, but it turns out that Ruby’s for has the same problem:
subs = [];
for i in 0..4
subs << lambda { i }
end
subs[0].call # => 4Which is one reason why sensible Ruby programmers don’t use for. If I were writing the snippet in ‘real’ Ruby, I’d write:
subs = (0..4).collect { |i|
lambda { i }
}
subs[0].call # => 0My conclusion
Javascript is weird. Okay, so you already know this. In so many ways it’s a lovely language, but it does have some annoyingly odd corners.
I am not a rock star 16
I am not a rock star. I am a computer programmer. I think I’m quite a good one.
You are not a rock star either.
387,000 matches to that query. Can we all just… I don’t know… grow up please?
Mutter… grumble… chunter… I’m 40 you know!
Updates
I have it on reliable authority that James O’Kelly is a Ruby on Rails Rockstar that would make a great addition to any team!
Martin Fowler's big mouthful 8
Martin Fowler is writing a book about Domain Specific Languages and, because you could never accuse Martin of a lack of ambition, he’s trying to write it in a reasonably (implementation) language agnostic fashion.
It’s fairly easy to write an implementation language agnostic book about old school DSLs, what used to be called little languages – there’s a fairly well established literature and theory to do with lexing, parsing and interpreting. These are all about algorithms, and algorithms are implementation language neutral by their very nature.
Where Martin has his work cut out for him is trying to talk about what he calls ‘internal DSLs’ and what I’ve been calling ‘pidgins’. These are the sorts of languages where you don’t write a lexer or parser but instead build a family of objects, methods, functions or whatever other bits and pieces your host language provides in order to create a part of your program that, while it is directly interpreted by the host language, feels like it’s written in some new dialect.
The Lisp family of languages can be said to be all about this. A good ‘bottom up’ lisp programmer will shape a language to fit the problem space, essentially building a new lisp which makes it easy to solve the problem at hand. Lisp’s minimal syntax, powerful macros and the way it blurs the boundary between code and data really support this style.
Once you move from Lisp to more ‘syntaxy’ languages, things get hairier. As Martin himself says
Another issue with book code is to beware of using obscure features of the language, where obscure means for my general reader rather than even someone fluent in the language I’m using. [...] this is much harder for a DSL book. Internal DSLs tend to rely on abusing the native syntax in order to get readability. Much of this abuse involves quirky corners of the language. Again I have to balance showing readable DSL code against wallowing in quirk.
He’s dead right. When I’m thinking about writing a pidgin in Ruby for instance, my first thought is usually to start with some kind of tabula rasa object which I can use to instance_eval a block. That lets me start to shape my language by lexically scoping the change:
in_pidgin do
...
end
But, though it’s easy to illustrate what I’d do with my tabula rasa, the implementation is somewhat tricky, and the tricks needed are unique to Ruby.
That sort of construct’s not really available to someone trying to write a pidgin in Java or Perl. In Perl, there are other odd corners of the language that can be abused to good effect. Dynamic scoping can let you ‘inject’ methods into a block even though there’s no Perl equivalent to instance_eval, or you can do some quite staggering things with the otherwise really annoying Perl function prototypes. For instance, here’s part of a Jifty definition of a persistent object:
column title =>
type is 'text',
label is 'Title',
default is 'Untitled post';
column body =>
type is 'text',
label is 'Content',
render_as 'Textarea';
Doesn’t look much like Perl does it? But it’s parsed and executed by perl with no source filters or eval STRING in sight. And there’s no unsightly :symbols scattered about the place either come to that.
These things all work by making the language do something unexpected, and generally, the way to do that is by knowing your host language inside out and playing with it. One of Damian Conway’s more inspired moments in recent years was List::Maker, in which the good doctor managed to find a corner of Perl where he could wedge a proper old school, complete with full on parser to build the AST, Little Language right in the heart of Perl without it looking like he was taking a plain old string and interpreting it. So, having found this odd little corner, he proceeded to implement a remarkably neat tool for building complex lists that are beyond the capabilities of Perl’s .. operator.
@odds = <1..100 : N % 2 != 0 >;
@primes = <3,5..99> : is_prime(N) >;
@available = <1..$max : !allocated{N} >
You may not think that’s all that sexy, but, and trust me on this, it’s just gorgeous. Yet more proof that Damian Conway is an (evil) genius.
Frankly, once you’ve seen the best of the pidgins available in Perl, some of highly praised ‘DSLs’ in Ruby start to look a bit ordinary. Ruby makes a great deal of stuff that a pidgin breeder needs to do really easy. In Perl it’s often rather hard with a huge amount of hoopage to deal with. But some of the things that are hard in Perl are impossible in Ruby.
Anyhoo… coming back to my point. I do find myself wondering if Martin’s bitten off more than he can chew in attempting to write a book that covers implementing pidgins without getting bogged down in the nitty gritty of individual languages. The problem he’s facing is that different languages don’t just have different quirks, they have different idioms too. What reads naturally in the context of a Ruby program will read very weirdly in, say Java or a lisp. Any patterns of implementation beyond broad (but important) strokes like “Play to your host language’s strengths” will surely end up as language specific patterns. Designing and implementing a good pidgin is hard. Doing it effectively means getting down and dirty with your host language and its runtime structures. And that’s not the sort of thing you can cover effectively in a language agnostic book.
Martin, if you’re reading this, good luck. I think you’re going to need it. I look forward to being proved wrong.
Things that make a developer cry 6
So, we’re doing a cobranding exercise at work. The idea being we serve up a branded version of amazing tunes in a subdomain of our partner, their users get a skinned version of the site that feels like part of the partner’s site, we get an influx of new users and everybody is happy. One aspect of this is we’re using the partner’s site to handle authentication.
Today, we got all our ducks in a row and started authenticating against the partner’s SOAP service as part of our user testing. So off I went to the partner site and set up an account…
At amazing tunes, we’re pretty scrupulous about password security, we never store plaintext passwords, any request that involves a password being sent is done over an https connection. It’s just the right thing to do.
After I’d finished setting up my account on the partner’s website I was presented with a screen that looked something like:
Your username is: pdcawley
Your password is: fucknuckle
At least it was an https connection, but it doesn’t exactly fill me with delight.
Today's Noun is: Reticence 2
What does the OED say reticence is?
Reticence: Maintenance of silence; avoidance of saying too much or of speaking freely; disposition to say little.
Pretty straightforward. When I chose reticence as one of my five nouns for programmers it was another reminder that objects are not the same as datastructures. Well designed objects keep their cards (instance variables) close to their chest. Client code tells objects what to do, it doesn’t ask them to kiss and tell. In Smalltalk Best Practice Patterns, (you don’t have a copy yet? Are you mad?) Kent Beck recommends that you put your accessor methods in the private protocol unless you have a very good reason for indicating that the accessors should be used by clients by putting the accessors in, say, the accessing protocol or some other, more suitably named, protocol. (In Smalltalk, all methods are public, but you can and should organize them into protocols/categories, either by choosing some existing protocol, or coming up with a new protocol name). In less flexible OO languages, you should probably at least mark your accessors as protected unless you have the aforementioned very good reason.
What about parameter objects then?
One obvious ‘exception’ to the rule of reticence is the parameter object. Say you have an unwieldy method that takes a bunch of arguments and fills the screen with its implementation. Being a conscientious programmer, you want to apply the ‘composed method’ pattern to the method so you’ll still end up with a screen’s worth of code, possibly more, but the individual methods will be much more focussed in what they achieve. What stops you is that bunch of parameters which are used through out the method. So, you introduce a parameter object. Bundle up the parameters into a single object, replace each parameter variable in the body of the code with an accessor call on the parameter object, and have at it. You can extract methods easily and you’ll only ever have to pass a single object.
It’s tempting not to bother creating a ‘real’ object, it’s very easy to just use an options hash, a la Ruby on Rails. And, because the options hash is a common pattern through your code, you can start adding helper methods like with_options, and you’ll get an awful lot of leverage out of it.
However, what’s often missed in discussions of the parameter object pattern is that it’s a waystation, not a destination. It may be handy, but if you persist in treating it as a datastructure, you’re missing out on the good stuff. Now you have a parameter object, you can start to move behaviour onto the parameter object and before you know it you’ll end up with a real object doing real, testable (mockable?), work.
Homework
Find a method where you’re using an options hash. Try using that hash to build a parameter object and then apply the principle of reticence. What happens to it? Where does the behaviour go? If, like me, you’ve come to OO from procedural coding styles, making your objects reticent is not a natural thing to do, it can feel extremely odd. But the more you practice it, the better you’ll get at thinking in a truly object oriented fashion. Sometimes an options hash really is the way to go, but not as often as you’d think.
Try it, maybe you’ll be converted.
Slide Of The Conference 7
Britt Selvitelle of Twitter gave a cracking talk at RailsConf Europe about scaling Rails applications to Twitter scale. It was great. Full of advice that we shall definitely be taking on board as we continue to develop amazing tunes. However, the last slide before the inevitable “Any Questions?” was the slide of the conference. It read:
It’s 2007. Every spammer has your email address. Put it on your goddamn webpage so people can get ahold of you about interesting things
I was the only person in the room who applauded.
I’m enough of an old fart (I was 40 a couple of Saturdays ago. I don’t think I’m properly old, but, on the net it feels positively ancient) that I remember getting annoyed at people obfuscating their sender addresses so that I couldn’t simply hit r in rn to reply to them directly rather than wibbling on channel. This was especially annoying when I was replying with an answer to a question they’d asked.
In the (my stats tell me) unlikely event that you’re reading this directly on the webpage, you’ll see my email address, complete with mailto: link. The wayback machine tells me it’s been there since at least February 2006, I’ve been using the same email address, unobfuscated, on mailing lists, newsgroups, business cards and presentation slides for over 10 years now. Yes, I get spammed, so will you. So do you, I’ll bet. But I’ll pay the cost of making it easy for spammers if it also makes it easy for people I want to hear from to get in touch with me. Spammers are predictable; that’s why spamfilters work most of the time. Interested people – people who are prepared to send me relevant mail – are golden.
The marketing types will tell you that clicks cost money. Every screen your customer has to go through before you get her money is another place she could decide she has better things to do. And, presumably, she is going to get something tangible at the end of that process so she’s motivated to go all the way through the process.
Someone who wants to send you email has far less motivation than that. The reader who thinks, “Ooh, Piers has missed something there, but I the comment box is the wrong place to bring it up.” or “Ooh, Piers Cawley, I haven’t seen him since we were at university, I should drop him a line” will be far more likely to act on that impulse and send that mail if it’s one click away. If they have to go and google my address from an obscure newgroup, or crack pdcawley [at] bofh [dot] org [dot] uk, or some other fatuous scheme designed to hide me from bad guys who already know where I live…
You’re intelligent people; you know what’s going to happen.
Seriously, would it kill you to publish your contact details on your website?
Tangentially
One of the RSS feeds I follow is a technorati feed of blogs linking to Typosphere. It’s a reasonably good way of seeing what people are saying about Typo (even if it’s simply “I’m switching to Mephisto/Wordpress/Whatever”). However, a few days back, the feed told me that someone had said:
Sorry, comments are broken. Please send complains to Typo.
So, being a conscientious Typo maintainer, I thought I’d drop him a line and ask for a few more details to see if we could track down the root of his problem. No email on the page. No obvious pointers to an email address.
He might be paranoid on his blog, but he’s not paranoid enough to avoid spammers. I found his email on the first page of google results, but I only bothered to look because I was inspired by Britt’s slide to write this. I guess I should drop him a line and see if we can’t sort it out.
A tiny ruby niggle 32
You know what? I’m starting to miss compulsory semicolons as statement terminators in Ruby.
“What?” I hear you say. “But not needing semicolons is one of Ruby’s cardinal virtues! Are you mad?”
I don’t think so, but maybe you’ll disagree after I explain further.
Here’s a piece of code that I might write if semicolons were the only way of terminating a statement:
Category.should_receive(:find_by_permalink)
.with('foo')
.and_return(mock_category);Or how about a complex find query
def find_tags_for(tag_maker, order = 'count')
klass = tag_maker.class
find :all
, :select => 'tags.*, count(tags.id) count'
, :group => Tag.sql_grouping
, :joins =>
"LEFT JOIN taggings ON "
+ " tags.id = taggings.tag_id "
+ "LEFT JOIN bookmarks ON "
+ " bookmarks.id = taggings.taggable_id "
+ " AND taggings.taggable_type = 'Bookmark' "
+ "LEFT JOIN #{klass.table_name} ON "
+ " #{klass.table_name}.id = bookmarks.#{klass.to_s.underscore}_id"
, :conditions => conditions_for(tag_holder)
, :order => (order == 'count')
? 'count(tags.id) desc, tags.name'
: "tags.name"
, :readonly => true
;
endI first came across the idea of the leading comma in Damian Conway’s excellent Perl Best Practices. The idea is that, by leading with the comma it’s very easy to add a new argument to an argument list or hash specification without having to remember to stick a comma on the end of the preceding line if it was at the end, and also, the leading comma makes it very plain that the line is a continuation of its predecessor in some way.
To make the examples work in Ruby, you have to add a \ to the end of each line that has a continuation, so the first example has to be written:
Category.should_receive(:find_by_permalink) \
.with('foo') \
.and_return(mock_category);Lining up the \s helps to stop them disappearing, but it’s an awful faff.
What tends to happen (in the rails source especially) is that ruby programmers simply don’t break their lines up. A quick search of the rails source finds plenty of lines more than 160 characters long.
Of course, some will argue that it doesn’t matter, that the old 80 column limit is a silly hangover from the days of steam when the only way to interact with your code was through an 80 column, green phosphor terminal. They have a point. An arbitrary line limit is silly, and we should get over it, especially in source code. However, unless you’re going to go around with every window open to its maximum width, lines will wrap, and they won’t do it nicely, or respect the indentation conventions of your language. Long lines are murder in diffs too, finding the point of difference is so much easier when your eye doesn’t have to scan an epic line.
It’s a shame there’s no way of forcing ruby’s parser to require semicolons as statement terminators for those programmers like me who think that the restriction that a statement must end with a semicolon is worth the freedom to break lines where we like without needing to escape every line break. It’s a shame too that popular tools like Textmate are so clumsy when it comes to dealing with line breaks. I would attempt to hold Emacs up as a paragon in this respect, but its Ruby mode tends to get a wee bit bemused once you start breaking lines, so that’s no good.
Domino theory
It’s amazing how far reaching seemingly simple language design decisions can be isn’t it? Just getting rid of the need to terminate statements with a semicolon has an enormous effect on they way code in ruby looks. I’m just not sure that they look better.
Maybe Smalltalk got it really right – they chose to use the most valuable syntactic character of all, the space, to denote sending a message. That freed up the . for use as a statement (sentence?) terminator. Then that freed up ; for use in one of Smalltalk’s most distinctive patterns – the cascade. Where a Rails programmer might write:
form_for(@comment) do |f|
f.input(:author)
f.input(:title)
f.input(:body)
endA Smalltalk programmer might eliminate the need for a temporary variable by doing:
Comment>>printOn: html
(html formFor: self)
input: #author;
input: #title;
input: #body.All those input: ... messages get sent to the result of html formFor: self. Once you get the hang of it, it’s a really sweet bit of syntax.
Incidentally, there’s been some discussion on the squeak mailing lists of a companion to the cascade, which would use a ;; as a sort of ‘pipe’. The idea is to be able to replace code like:
((self collect: [:each | each wordCount)
inject: 0 into: [:total :each| total + each])
printOn: aStream.with
self collect: [:each | wordCount]
;; inject: 0 into: [:total :each | total + each]
;; printOn: aStream.(NB: Please ignore what those code snippets do, because that’s gruesome. Concentrate on how they do it).
Nobody’s quite proposed going as far as Haskell does with its Monads, which can be thought of as a magical land where the meaning of the semicolon changes according to what sort of Monad you’re in. (In an IO monad for instance, the semicolon imposes an evaluation order. In some other monad, the semicolon could just as easily denote a backtracking point). Then again, there’s nothing to stop the dedicated Smalltalker implementing something Monadish – every Smalltalk class can specify how its methods should be compiled after all…
In conclusion…
I’m not sure I’ve got a real conclusion for all this. I’m mostly musing. However, I do think it’s useful to think carefully about restrictions and what they free us to do as programmers. Lispers will wax lyrical about the way that their language’s pared down syntax lets them do amazing things with macros. Smalltalkers will defend to the death the idea that the only way to do anything is to send messages to objects. Pythonistas love their syntactic whitespace. Haskellers love their static typing (admittedly, they have an incredibly flexible notation for expressing type that leaves most other programming languages standing).
And any English speaker with ears will know that a poem like Dylan Thomas’s Do Not Go Gentle Into That Good Night gains much of its power from it’s form, the villanelle, one of the most restricted forms of poetry there is. Two lines repeating through the poem and a staggering number of rhymes to find:
Do not go gentle into that good night,
Old age should burn and rave at close of day;
Rage, rage against the dying of the light.
Though wise men at their end know dark is right,
Because their words had forked no lightning they
Do not go gentle into that good night.
Good men, the last wave by, crying how bright
Their frail deeds might have danced in a green bay,
Rage, rage against the dying of the light.
Wild men who caught and sang the sun in flight,
And learn, too late, they grieved it on its way,
Do not go gentle into that good night.
Grave men, near death, who see with blinding sight
Blind eyes could blaze like meteors and be gay,
Rage, rage against the dying of the light.
And you, my father, there on the sad height,
Curse, bless me now with your fierce tears, I pray.
Do not go gentle into that good night.
Rage, rage against the dying of the light.
If that’s not making a virtue of a restriction, I don’t know what is.
