There was a discussion on StackOverflow about useful alternative control structures.. One member mentioned that he would like to have an alternate control structure that would cycle through a list of possibilities.
This structure is available already in some languages: Python has it in itertools.cycle and Haskell has the function cycle in its Prelude.
But if you don’t use Python or Haskell, but your language does have closures, you can implement it yourself. Here’s how in JavaScript.
function cycle(choices) {
var i = 0;
return function () {
var current = i;
i = (i + 1) % choices.length;
return choices[current];
};
}
Simple, isn’t it? Here’s a brief explanation of how it works. Inside the body of cycle, there are two local variables, i and choices. They are also available to the anonymous function that’s returned by the function, but the interesting thing is that although i and choices fall out of scope when cycle returns, the anonymous function still has a reference to them and can access and modify them as it needs to. When the anonymous function is called, it returns the current element from choices and moves i to “point” to the next element.
Here are some sample usages:
var colors = cycle(["blue", "white", "red"]); // colors is a function
for (var i = 0; i < 5; ++i) {
console.log(colors());
}
// Output:
// bleu
// white
// red
// blue
// white
var salutations = cycles([
function (s) { return "Hello " + s; },
function (s) { return "Good morning " + s; },
function (s) { return "Hey " + s; }
]);
for (var i = 0; i < 3; ++i) {
console.log(salutations()("world"));
}
// Output:
// Hello world
// Good morning world
// Hey world
If you are not familiar with closures and your favorite language supports them, I recommend that you find a tutorial (many are available online using JavaScript) to learn and appreciate their power.
Hi,
Nice post!
Two observations:
1. In the first code, instead of ‘current’ you mean ‘i’, right?
2. You could use <sourcecode language=’javascript’> and <\sourcecode> (change the < > for [ ]) environment. I think the code would be better rendered.
Ops, forget my first observation :P