Hobby-hacking Eric

2009-01-30

haskell-ji

As a programmer, I find myself struggling with a lot of really mundane and stupid-looking issues like "how should I name my variables", or "should acronyms be kept upper case (XML), or smooshed down for easier CamelCasing (Xml)?" and finally "what order should my code go in?"

These questions do not so much keep me up and night, but cause me an inordinate amount of flip-flopping in my code. Not remembering my preference du jour, I'll sometimes do things four different ways in code and later on suffer because I forgot that in one bit of code, I had named something parseXML and in the other bit, I had named it xmlParse.

The good news is that things are settling down on at least one front. It seems that all the versions of Eric past and present are settling on a consensus on How To Lay Code Out. The result is a set of directional tips, akin to the kind of thing you learn when you are writing Chinese Hanzi (Japanese Kanji):
  1. Types before code
  2. High-level before low-level -- For example, generally using where instead of let...in, but also "higher-level" functions first, "detail" functions later
  3. Input before output -- It's not that this was ever up for debate, it's just that sometimes, I'll write it the other way without realising that I'm doing it.
  4. Odds and ends last -- At the very end of my code: an odds-and-ends section for all those little snippets of code you copy around but are that too small to justify making a library, e.g.
    buckets :: Ord b => (a -> b) -> [a] -> [ (b,[a]) ]
    buckets f = map (\xs -> (f (head xs), xs))
    . groupBy ((==) `on` f)
    . sortBy (compare `on` f)
    Do you have an odds-and-ends.hs file on your computer?
Notice that the tips are not always compatible with each other, but they do sort of point in the same general direction.

Phew, I'm glad I'm starting to get at least this bit sorted. I really hope it reduces the amount of pointless erician flip-flopping. It's no big deal -- civilisation does not collapse because of inconsistent case conventions -- but it is a nuisance. This kind of thing is on the order of silly American-style dates vs. European-style dates causing confusion, where we could all just be using International yyyy-mm-dd dates, and while we're at it, 24 hour time, the metric system and A4 paper...


7 comments:

b/k said...

So, is it xmlParse or parseXML?

kowey said...

Heh, I wish I knew! I think I'm leaning more towards smooshing (Xml), no comments on what order bits of names should be in :-)

Nathan said...

I, some random dude on the internet, have recently come to basically the same conclusions you just listed. So I guess we can both feel happy about it.

Christophe Poucet said...

Buckets could be made better (though slightly more verbose) as follows:

buckets :: Ord b => (a -> b) -> [a] -> [ (b,[a]) ]
buckets =
map (first head)
. map unzip
. groupBy ((==) `on` fst)
. sortBy (compare `on` fst)
. map (\x -> (f x, x))


This way you compute 'f' only once for each element.

kowey said...

Thanks for the new buckets! (and the comments)

PO8 said...

I understand the appeal of "high-level to low-level" aka "leave the details til the end." As a student of these problems in a variety of languages over a long time, however, I'm afraid that I must respectfully disagree.

In the English-speaking world, at least, we learn to read left-to-right top-to-bottom at an early age. It becomes an ingrained habit. And when we learn to read and write stories, we tell things as we need them, rather than saving details until the end.

I'm convinced that, as a result of all this training, if you want your code to tell a story, you should introduce things as they become important, and not defer. This means that the "details" of your program will be introduced when they become timely; they may be intermixed, but will tend to be earlier rather than later.

I think that making Haskell's "let" syntactically harder to use than its "where" was a cognitive mistake, and has encouraged an "upside-down" style of programming that is harder for novices to pick up and harder for everyone to work with.

Of course, I haven't done any formal research, and your mileage may vary.

kowey said...

Argh, you're making me dither! Don't make me dither :-D