+++*

Symbolic Forest

A homage to loading screens.

Blog : Posts tagged with ‘computing’

Going through things one by one

Or, a coding exercise

One of my flaws is that as soon as I’m familiar with something, I assume it must be common knowledge. I love tutoring and mentoring people, but I’m bad at pitching exactly where their level might be, and in working out what they might not have come across before. Particularly, in my career, software development is one of those skills where beyond a certain base level nearly all your knowledge is picked up through osmosis and experience, rather than through formal training. Sometimes, when I’m reviewing my team’s code I come across things that surprise me a little. That’s where this post comes from, really: a few months back I spotted something in a review and realised it wouldn’t work.

This post is about C#, so apologies to anyone with no interest in coding in general or C# in particular; I’ll try to explain this at a straightforward level, so that even if you don’t know the language you can work out what’s going on. First, though, I have to explain a few basics. That’s because there’s one particular thing in C# (in .NET, in fact) that you can’t do, that people learn very on that you can’t do, and you have to find workarounds for. This post is about a very similar situation, which doesn’t work for the same reason, but that isn’t necessarily immediately obvious even to an experienced coder. In order for you to understand that, I’m going to explain the well-known case first.

Since its first version over twenty years ago, C# has had the concept of “enumerables” and “enumerators”. An enumerable is essentially something that consists of a set of items, all of the same type, that you can process or handle one-by-one. An enumerator is a thing that lets you do this. In other words, you can go to an enumerable and say “can I have an enumerator, please”, and you should get an enumerator that’s linked to your enumerable. You can then keep saying to the enumerator: “can I have the next thing from the enumerable?” until the enumerator tells you there’s none left.

This is all expressed in the methods IEnumerable<T>.GetEnumerator()* and IEnumerator<T>.MoveNext(), not to mention the IEnumerator<T>.Current property, which nobody ever actually uses. In fact, the documentation explicity recommends you don’t use them, because they have easier wrappers. For example, the foreach statement.

List<string> someWords = new List<string>() { "one", "two", "three" };
foreach (string word in someWords)
{
    Process(word);
}

Under the hood, this is equivalent** to:

List<string> someWords = new List<string>() { "one", "two", "three" };
IEnumerator<string> wordEnumerator = someWords.GetEnumerator();
while (wordEnumerator.MoveNext())
{
    string word = wordEnumerator.Current;
    Process(word);
}

The foreach statement is essentially using a hidden enumerator that the programmer doesn’t need to worry about.

The thing that developers generally learn very early on is that you can’t modify the contents of an enumerable whilst it’s being enumerated. Well, you can, but your enumerator will be rendered unusable. On your next call to the enumerator, it will throw an exception.

// This code won't work
List<string> someWords = new List<string>() { "one", "two", "three" };
foreach (string word in someWords)
{
    if (word.Contains('e'));
    {
        someWords.Remove(word);
    }
}

This makes sense, if you think about it: it’s reasonable for an enumerator to be able to expect that it’s working on solid ground, so to speak. If you try to jiggle the carpet underneath it, it falls over, because it might not know where to step next. If you want to do this using a foreach, you will need to do it some other way, such as by making a copy of the list.

List<string> someWords = new List<string>() { "one", "two", "three" };
List<string> copy = someWords.ToList();
foreach (string word in copy)
{
    if (word.Contains('e'));
    {
        someWords.Remove(word);
    }
}

So, one of my colleagues was in this situation, and came up with what seemed like a nice, clean way to handle this. They were going to use the LINQ API to both make the copy and do the filtering, in one go. LINQ is a very helpful API that gives you filtering, projection and aggregate methods on enumerables. It’s a “fluent API”, which means it’s designed for you to be able to chain calls together. In their code, they used the Where() method, which takes an enumerable and returns an enumerable containing the items from the first enumerable which matched a given condition.

// Can you see where the bug is?
List<string> someWords = new List<string>() { "one", "two", "three" };
IEnumerable<string> filteredWords = someWords.Where(w => w.Contains('e'));
foreach (string word in filteredWords)
{
    someWords.Remove(word);
}

This should work, right? We’re not iterating over the enumerable we’re modifying, we’re iterating over the new, filtered enumerable. So why does this crash with the same exception as the previous example?

The answer is that LINQ methods—strictly speaking, here, we’re using “LINQ-To-Objects”—don’t return the same type of thing as their parameter. They return an IEnunerable<T>, but they don’t guarantee exactly what implementation of IEnumerable<T> they might return. Moreover, in general, LINQ prefers “lazy evaluation”. This means that Where() doesn’t actually do the filtering when it’s called—that would be a very inefficient strategy on a large dataset, because you’d potentially be creating a second copy of the dataset in memory. Instead, it returns a wrapper object, which doesn’t actually evaulate its filter until something tries to enumerate it.

In other words, when the foreach loop iterates over filteredWords, filteredWords isn’t a list of words itself. It’s an object that, at that point, goes to its source data and thinks: “does that match? OK, pass it through.” And the next time: “does that match? No, next. Does that match? Yes, pass it through.” So the foreach loop is still, ultimately, triggering one or more enumerations of someWords each time we go around the loop, even though it doesn’t immediately appear to be used.

What’s the best way to fix this? Well, in this toy example, you really could just do this:

someWords = someWords.Where(w => !w.Contains('e')).ToList();

which gets rid of the loop completely. If you can’t do that for some reason—and I can’t remember why we couldn’t do that in the real-world code this is loosely based on—you can add a ToList() call onto the line creating filteredWords, forcing evaluation of the filter at that point. Or, you could avoid a foreach loop a different way by converting it to a for loop, which are a bit more flexible than a foreach and in this case would save memory slightly; the downside is a bit more typing and that your code becomes prone to subtle off-by-one errors if you don’t think it through thoroughly. There’s nearly always more than one way to do something like this, and they all have their own upsides and downsides.

I said at the start, I spotted the issue here straightaway just by reading the code, not by trying to run it. If I hadn’t spotted it inside somebody else’s code, I wouldn’t even have thought to write a blog post on something like this. There are always going to be people, though, who didn’t realise that the code would behave like this because they hadn’t really thought about how LINQ works; just as there are always developers who go the other way and slap a ToList() on the end of the LINQ chain because they don’t understand how LINQ works but have come across this problem before and know that ToList() fixed it. Hopefully, some of the people who read this post will now have learned something they didn’t know before; and if you didn’t, I hope at least you found it interesting.

* Note. for clarity I’m only going to use the generic interface in this post. There is also a non-generic interface, but as only the very first versions of C# didn’t support generics, we really don’t need to worry about that. If you write your own enumerable you’re still required to support the non-generic interface, but you can usually do so with one line of boilerplate: public IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

** In recent versions of C#, at any rate. In earlier versions, the equivalence was slightly different. The change was a subtle but potentially breaking one, causing a change of behaviour in cases where the loop variable was captured by a lambda expression.

Code archaeology

When things become relevant again

One thing I have been doing over the past few weeks is: finally, finally, taking the hard drive out of my last desktop computer—last used about 8 years ago at a guess—and actually copying all the documents off it. It also had stuff preserved from pretty much every desktop machine I’d had before that, so there was a whole treasure-chest of photographs I hadn’t seen in years, things I’d written, and various incomplete coding projects.

Some of the photos will no doubt get posted on here over the coming weeks, but this post isn’t about those. Because, by pure coincidence, I was browsing my Twitter feed this morning and saw this tweet from @ireneista:

we were trying to help a friend get up to speed on how to make a Unix process into a daemon, which is something we found plenty of guides on in the 90s but it’s largely forgotten knowledge

Hang on a minute, I think. Haven’t I just been pulling old incomplete coding projects off my old hard disk and saving them into Github repositories instead? And don’t some of those have exactly that code in? A daemon, on Unix, is roughly the equivalent of a “Service” on Windows. It’s a program that runs all the time in the background on a computer, doing important work.* Many servers don’t even run anything else to speak of. On both Unix and Windows systems, there are special steps you have to take to properly “detach” your code and let it run in the background as part of the system, and if you don’t do all those steps properly you will either produce something that is liable to break and stop running that it’s not supposed to, or write something that fills up your system’s process table with so-called “zombie” entries for processes that have stopped running but still need some bookkeeping information kept about them.

Is this forgotten knowledge? Well, it’s certainly not something I would be able to do, off the top of my head, without a lot of recourse to documentation. For a start all the past projects I’m talking about were written in C, for Linux systems, and I haven’t touched the language nor the operating system much for a number of years now.

None of the projects I’m talking about ever approached completion or were properly tested, so there’s not that much point releasing their full source code to the world. However, clearly, the information about how to set up a daemon has disappeared out of circulation a bit. Moreover, that code was generally stuff that I pulled wholesale from Usenet FAQs myself, tidying it up and adding extra logging as I needed, so compared to the rest of the projects, it’s probably much more reliable. The tweet thread above links to some CIA documentation released by Wikileaks which is nice and explanatory, but doesn’t actually include some of the things I always did when starting up a daemon. You could, of course, argue they’re not always needed. So, here is some daemonisation code I have cobbled together by taking an average across the code I was writing about twenty-ish years ago and adding a bit of explanation. Hopefully this will be useful to somebody.

Bear in mind this isn’t real code: it depends on functions and variables that you can assume we’ve declared in headers, or in the parts of the code that have been omitted. As the old saying goes, I accept no responsibility if this code causes loss, damage, or demons flying out of your nose.**

/* You can look up yourself which headers you'll need to include */

int main(int argc, char **argv)
{
    /* 
     * First you'll want to read config and process command line args,
     * because it might be nice to include an argument to say "dont'
     * run as a daemon!" if you fancy that.
     *
     * This code is also written to use GNU intltools, and the setup for that
     * goes here too.
     */

    /* Assume the daemonise variable was set by processing the config */
    if (daemonise)
    {
        /* First we fork to a new process and exit the original process */
        switch (fork ())
        {
        case -1:
            syslog (LOG_ERR, _("Forking hell, aborting."));
            exit (EXIT_FAILURE);
        default:
            exit (0);
        case 0:
            break;
        }

        /* Then we call setsid() to become a process group leader, making sure we are detached
         * from any terminals */
        if (setsid () == -1)
        {
            syslog (LOG_ERR, _("setsid() failed, aborting."));
            exit (EXIT_FAILURE);
        }

        /* Then we fork again */
        switch (fork ())
        {
        case -1:
            syslog (LOG_ERR, _("Forking hell x2, aborting."));
            exit (EXIT_FAILURE);
        default:
            exit (0);
        case 0:
            break;
        }

        /* Next, a bit of cleanup.  Change our CWD to / so we don't block any umounts, and 
         * redirect our standard streams to taste */
        umask (0022);
        if (chdir ("/"))
            syslog (LOG_WARNING, _("Cannot chdir to root directory"));
        freopen ("/dev/null", "w", stdout);
        freopen ("/dev/null", "r", stdin);
        freopen ("/dev/console", "w", stderr); /* This one in particular might not be what you want */

        /*
         * Listen to some signals.  The second parameters are function pointers which 
         * you'll have to imagine are defined elsewhere.  Reloading config on SIGHUP
         * is a common daemon behaviour you might want.  I can't remember why I thought
         * it important to ignore SIGPIPE
         */
        signal (SIGPIPE, SIG_IGN);
        signal (SIGHUP, warm_restart);
        signal (SIGQUIT, graceful_shutdown);
        signal (SIGTERM, graceful_shutdown);

        /* And now we're done!  Let's go and run the rest of our code */
        run_the_daemon ();
    }
}

The above probably includes some horrible mistake somewhere along the way, but hopefully it’s not too inaccurate, and hopefully would work in the real world. If you try it—or have opinions about it—please do get in touch and let me know.

* NB: this is a simplification for the benefit of the non-technical. Yes, I know I’m generalising and lots of daemons and services don’t run all the time. Please don’t write in with examples.

** “demons flying out of your nose” was a running joke in the comp.lang.c Usenet group, for something it would be considered entirely legitimate for a C compiler to do if you wrote code that was described in the C language standard as having “undefined behaviour”.

Hello, Operator

In which we consider switching OS

Right, that’s enough of politics. For now, at least, until something else pops up and ires me.

Back onto even shakier ground, so far as quasi-religious strength of feeling goes. I’m having doubts. About my operating system.

Back in about 1998 or so, I installed Linux on my PC. There was one big reason behind it: Microsoft Word 97. Word 97, as far as I can remember it, was a horribly bug-ridden release; in particular, when you printed out a long document, it would skip random pages. I was due to write a 12,000 word dissertation, with long appendices and bibliography,* and I didn’t trust Word to do it. I’d had a flatmate who had tackled the same problem using Linux and LaTeX, so I went down the same route. Once it was all set up, and I’d written a LaTeX template to handle the university’s dissertation- and bibliography-formatting rules, everything went smoothly. And I’ve been a happy Linux user ever since.

Now, I’m not going to move away from Linux. I like Linux, I like the level of control it gives me over the PC, and the only Windows-only programs I use run happily under Wine. What I’m not sure about, though, is the precise flavour of Linux I use.

For most of the past decade, I’ve used Gentoo Linux. I picked up on it about a year after it first appeared, and liked what I saw: it gives the system’s installer a huge amount of control over what software gets installed and how it’s configured. It does this in a slightly brutal way, by building a program’s binaries from scratch when it’s installed; but that makes it very easy to install a minimal system, or a specialist system, or a system with exactly the applications, subsystems and dependancies that you want.

There are two big downsides to this. Firstly, it makes installs and updates rather slow; on my 4-year-old computer, it can take a few hours to grind through an install of Gnome or X. Secondly, although the developers do their best, there’s no way to check the stability of absolutely every possible Gentoo installation out there, and quite frequently, when a new update is released, something will break.**

I’m getting a bit bored of the number of times in the last few months that I’ve done a big update, then find that something is broken. Sometimes, that something major is broken; only being able to log in via SSH, for example, because X can’t see my keyboard any more.*** It can be something as simple as a single application being broken, because something it depends on has changed. It turns “checking for updates” into a bit of a tedious multi-step process. I do like using Gentoo, but I’m wondering if life would be easier if I switched over to Ubuntu, or Debian, or some other precompiled Linux that didn’t have Gentoo’s dependancy problems.

So: should I change or should I go stay? Can I be bothered to do a full reinstall of everything? What, essentially, would I gain, that wouldn’t be gained from any nice, clean newly-installed computer? And is it worth losing the capacity to endlessly tinker that Gentoo gives you? I’m going to have to have a ponder.

UPDATE: thanks to K for pointing out that the original closing “should I change or should I go?” doesn’t really make much sense as a contrast.

* The appendices took up the majority of the page count, in the end, because of the number of illustrations and diagrams they contained.

** Before any Gentoo-lovers write in: yes, I am using stable packages, and I do read the news items every time I run “emerge –sync”

*** I was lucky there that SSH was turned on, in fact; otherwise I’d have had to start up and break into the boot sequence before GDM was started.

Brokenness

In which things go wrong in hard-to-diagnose ways

We go away for the weekend. We come back. And the house is cold. Turn on the hot water tap: freezing. The boiler has given up the ghost.

I turn on the PC this morning: and that refuses to come on, too. Which, to be honest, is a recurrence of a problem I was already aware of. Sometimes, on start up, it gets partway and loses contact with the disk drive. Or, sometimes, if you ask it to do too much disk-thrashing just after booting, the same thing happens. On the other hand, if it starts up all its services and is fine for 15 minutes, it will probably stay fine until it’s switched off.

All that points to something like a loose contact somewhere, if you ask me. As I say, it’s been happening for months now; but today I was in the mood to sort it. The computer now has a new hard disk cable. It booted up first time, and it’s still running. Let’s see if it still works in the morning.

The boiler might be suffering from something similar. The gas engineer came out, poked around at it, and fixed it. The chap wasn’t sure what the problem was, or how he fixed it, but fix it he did. Maybe. It’s working now, but we still have to see if that, too, will come on again come tomorrow.

New World

In which we jumble the letters up

K was digging through her boxes of zines last night, hunting for something, and came across one she thought I’d find interesting. She passed it over. It was The Dvorak Zine – “changing the world, one keyboard at a time”.

I’ve heard of the Dvorak keyboard before. It’s a keyboard layout specifically designed to make typing quicker, and easier to learn. I’d never bothered, though, to investigate it, and find out what the layout actually is. The zine, though, is cunningly designed. The back page is a keyboard map; you prop it up on your desk and start typing away.

I’m not a proper typist. I’ve never learned to touch-type. My typing is pretty fast for someone who can’t type; but really it’s nothing more than very fast two-finger typing. As a result, it’s riddled with mistakes, and I spend more time going back and correcting what I’ve done than it takes to type the words in the first place. The Dvorak keyboard, though, seems specifically designed for touch-typing – and, looking at keys that type different letters to the letters printed on them would just be far too confusing for me. So, I thought: an ideal opportunity. Why don’t I learn?

So, this morning, I set the zine up on my desk, and switched the keyboard mode over. Put my fingers on the home keys, and started typing: one letter at a time.

It was slow, of course it was. But, as promised, it was surprising how quick it was to pick up. Within a couple of hours, it was quicker to type without looking at the keyboard map than to use it. This might actually work.

To be honest: I haven’t used it to type this. I did want to get something productive done today, so after 3 hours or so of Dvorak typing I switched back to the traditional layout. I don’t want to lose my ability to type the old way, after all: we don’t have a Dvorak typewriter and we’re unlikely to find one. I’m very pleased with how quickly I’ve been able to pick Dvorak up, though. What mostly slows me down is: like most people, I think in terms of words rather than letters. I seem to mostly type using my muscle memory of whole words and word fragments. Switching to Dvorak, I can easily remember where all the common letters are and which finger to use for them: but then I have to spell each word out in my head to type it. Training myself to type in words, without thinking about the spelling, will take some time.

Lost terminology

In which a word is snappy but fails to catch on

Jargon changes over the years; bits of it get picked up, some bits become mainstream, and some wither away.

On a trip to Wet Yorkshire the other day, I started thinking: there’s one piece of jargon which I think it’s a shame didn’t get picked up. It’s Charles Babbage‘s term mill, which he used to name something that was, for him, a new concept: a machine which would carry out arithmetic calculations according to a sequence of instructions. Today, we’d call it a computer CPU; but there isn’t really any better term for it other than that awkward three-syllable abbreviation. I’d much rather be talking about the newest Core Duo mill, or Athlon mill; it rolls off the tongue. A twin-mill machine sounds much snappier than a dual-processor one. If you look at one under a microscope, it even looks vaguely like the giant mechanical grids of 19th-century looms,* just like the mills Babbage was originally alluding to. Is there any chance of the word making a come-back? Probably not; but it would be nice if it did.

* I was tempted to take up “loom” and segue into a Doctor Who discussion, but that reference would be too geeky even for me.

Grumble grumble

In which we have problems

Well, in addition to not being able to find any of the Christmas presents I want to buy in the shops; the computer has started misbehaving. It crashed in the middle of an update, and hasn’t been working right ever since. For those of you who have been on the internet since the early 90s: I’m posting this using the text-only browser Lynx. because it was the only one I could get working quickly whilst getting the rest of the machine back on its feet.

So if anything in this post looks a bit strange, that’s because I can’t really see what I’m doing, because the text-entry widget in Lynx is a bit…

The Plain People Of The Internet: So what was the explanation for all those other posts looking a bit strange, then?

Me: Har har.

More whining posts tomorrow; or if I’m in a good mood, I’ll tell you about the pantomime I went to see.

Update: Although Lynx lets you create posts in WordPress, it doesn’t seem to like you editing them. Grrr, again.

Tick tock

In which the ancient Greeks can calculate

In the news recently: the Antikythera Mechanism, a cunning ancient device which, it turns out, could predict planetary positions and eclipses. It was first discovered around a hundred years ago, but it has always been little-known. Partly, I’m sure, because of the domination of Greek archaeology by classisists and historians. The Antikythera mechanism is unique, and its purpose unclear without careful analysis, so it’s not too surprising that for most of the time since its discovery it lurked, little-known, in an Athens museum.

Around 1980, Richard Feynman wrote about the mechanism, in a letter to his family:

Amongst all those art objects [in the museum] there was one thing so entirely different and strange that it is nearly impossible. It was recovered from the sea in 1900 and is some kind of machine with gear trains, very much like the inside of a modern wind-up alarm clock. The teeth are very regular and many wheels are fitted closely together. There are graduated circles and Greek inscriptions. I wonder if it is some kind of fake. There was an article on it in the Scientific American in 1959.

I asked the archaeologist lady about the machine in the museum—whether other similar machines, or simpler machines leading up to it or down from it, were ever found—but she hadn’t heard of it. So I met her … at the museum to show it to her. She required some explanation from me why I thought such a machine was interesting … but after a bit she believed maybe it was striking, and she took me to the back rooms of the museum—surely there were other examples, and she would get a complete bibliography. Well, there were no other examples, and the complete bibliography was a list of three articles (including the one in the Scientific American)—all by one man, an American from Yale!*

It’s not that surprising that the Antikythera mechanism was little-studied for a long period. It’s an anomaly, at least as far as surviving records go, and anomalies are often ignored if they can’t be made to match up with everything else. It’s disappointing to me, in fact, that often the only people to treat anomalous objects seriously are pseudoarchaeologists, who nearly always come up with ridiculous conclusions. Pseudoarchaeologists are often condescending to the past in their own special way – “these people were too primitive to do this! Aliens must have helped them!” – but in many ways traditional archaeology can be just as condescending, by sometimes hunting things it does not understand out of the way, because they’re inconvenient or too complex to understand.

* published in What Do You Care What Other People Think?, the second book of Feynman’s memoirs.

On sucking

In which we discuss some design flaws in Lotus Notes

Spent quite a while last night reading Lotus Notes Sucks***, a collection of reasons why, as you could probably guess, Lotus Notes sucks. I have to use the thing at work every day, and it is indeed truly awful; but I didn’t really like the site. It lists 80-something superficial bad things about Lotus Notes, without listing any of the truly awful things about it.

Aside from the slightly smug nature of the site – every entry on it ends with “Conclusion: Lotus Notes Sucks”, repeated over and over again with the subtlety of a 10-ton cartoon weight – it’s written solely from the point of view of someone who uses Lotus Notes purely as an email program. That is, to be fair, probably what most people use it for; but that’s not what it is. It’s really a generic NoSQL non-relational database and data-sharing program that has been shoehorned into an email mould, and doesn’t properly fit. So, all the complaints are fairly trivial ones, and a lot boil down to: “it’s slightly different to Outlook”.

There are some true horrors inside Lotus Notes, if you ever have to do any programming or development work with it. The help files, for example, are all just specialised Notes data stores with a suitable interface on the front. This is completely fine, right up until you have a buggy bit of program code that you want to step through in the debugger.* If you’re running something in the debugger, you can’t access any other Notes data. Which, stupidly, includes the help files. Programmers have no access at all to the help files at the very time they’re most likely to need it.

There are other horrible things too. Things go wrong in unfixable ways. Files can mysteriously corrupt themselves and be unrepairable. If a file is deleted, shortcuts to it can become undeletable. If you accidentally delete half your email and ask your IT people to recover it from a backup, then unless IT knows the necessary cunning tricks,** when you open the backup copy of your mail file Notes will happily go “aha! this is the same datastore, but it’s out of date!” and delete everything in the backup too. Oh, joy. Lotus Notes Sucks doesn’t even mention some non-programming problems that I thought were obvious: you can’t search for empty fields, for example. You can search for documents where Field X contains “wibble”, no problem, but you can’t search for documents where Field X is blank. Well, you can do it if you’re a programmer and you write some code to do it for you, but there’s no way to trick the normal search interface into doing it.

In short, Lotus Notes is a horrible can of worms which will trip you up whenever you try to do something the programmers didn’t think of. So it’s a shame that Lotus Notes Sucks finds so many trivial surface-level problems with the email part of the program, when if you try to do more than just email with it, there are so many deeper faults lurking under the surface.

* Don’t worry if you don’t understand this. It means: run the program one line at a time so you can spot the point where it all goes wrong leading to your program falling over.

** Which we do, the second time someone does it, of course

*** Update, 27th August 2020: the site I originally linked to here has sadly disappeared.

Masochism

In which we go back to BASICs

No, I’m not a masochist.

I take a strange, geeky, masochistic pleasure, though, in making things hard for myself. In doing computer-based things the long way round. In solving the problems that are probably easy for some people, but hard for me. In learning new things just because it’s a new challenge.

Today, I was wrestling with a piece of Basic code in an Excel spreadsheet. I’ve not touched Basic since it had line numbers, which is a long long time ago, and I barely know any of it. I forced myself to work out, though, how to do what I wanted.* It was mentally hard work, and meant a lot of looking back and forth to the help pages, but I got it done in the end. It might not be written in the best way, the most efficient way, or the most idiomatic way.** But doing it was, strangely, fun.

* or, rather, what the consultant I was assisting wanted.

** for non-geeks: every computer language or system has its own programming idioms, which fit certain ways of programming particular problems. Someone used to language A will, on switching to language Z, often keep on programming in language A’s style even if this produces ugly and inefficient code in the other language.