Every other week, the Principle Studios engineering team gets together and challenges themselves to accomplish a tiny task given by one of the other team members. When we’re done, we share the results of the challenge and try to learn from each other - since there’s rarely one “right” way to accomplish even technical tasks. Sometimes these are simple, such as “write the types for this concept in TypeScript”, “use this feature in C# to accomplish this task”… and sometimes they’re a bit more open-ended.
This week, we were practicing a common but advanced programming language feature:
In many modern languages, closures are a popular technique for encapsulating state. In JavaScript, a simple closure might look like this:
const multiply = (a) => (b) => a * b; const double = multiply(2); console.log(double(2)); // outputs 4 console.log(double(3)); // outputs 6
I’m not going to go into too much detail on closures; there’s lots of information out there using the languages we use daily. If you look, you may find the solution to this week’s challenge, but if you’re already familiar, it should be quick anyway:
Write a function that returns a function that, when called, returns a number indicating the number of times the inner function was called.
A sample use of a solution, in this case called
createCounter
in TypeScript:const counter = createCounter(); const counter2 = createCounter(); console.log(counter()); // 1 console.log(counter()); // 2 console.log(counter2()); // 1 console.log(counter()); // 3 console.log(counter2()); // 2
Entries
This week, we had lots of entries, so we’ll group them by language.
JavaScript
We had the most entries in JavaScript, but the first that came in was a single-line implementation by Andrew Owen:
const createCounter = () => ((c) => () => ++c)(0)
Andrew also admitted that he was being “cryptic/clever on purpose” to get the solution down to one line, and it is not representative of what he’d actually write for production code!
The other JavaScript entries (from Aaron White, Tony Mishler, Megan Kossa, Kris Henderson, and Ben Cohen-Chen) were fairly similar and traditional. The following is Megan Kossa’s entry:
const createCounter = () => {
let count = 0;
return () => ++count;
};
The above sample is one of the most classic examples of a closure - the count
variable is “closed” over and gets captured each time createCounter
is called.
Again, there’s lots of explanations about closures already
available on the internet, so I won’t go into much depth here.
C#
Tony Mishler and Justin Rodriguez submitted entries in C#; Tony’s solution is below:
public static Func<int> CreateCounter(){
int i = 0;
Func<int> projection = () => ++i;
return projection;
}
C#‘s resulting code is almost identical to the JS implementations, just with added typings. (As such, TypeScript developers could grasp this concept quite quickly in C#!) I personally find it fascinating to use ILSpy to decompile source like this to see how the compiler implements closures; in C#, it’s a language feature, not an IL feature.
Go
Aaron White decided one solution was not enough and wanted to stretch his golang muscles. This one was fun for me, as I rarely have the opportunity to read Go, and I’ve never had the need to write it.
func createCounter() func() int {
ct := 0
return func() int {
ct++
return ct
}
}
It seems that in this regard, Go is structurally similar to C# and JS, except
the ++
operator is only a statement, not an expression.
Elixir
While we haven’t used it at Principle, Andrew Owen also provided a second entry in Elixir. I’ve heard great things about Elixir, but this is the first time I’ve seen any code beyond online tutorials for it - but like Go, I always enjoy seeing the same paradigms in different languages.
createCounter = fn ->
{:ok, agent} = Agent.start_link(fn -> 0 end)
fn -> Agent.get_and_update(agent, fn n -> {n, n+1} end) end
end
Elixir, which runs on the Erlang VM, has a very principled approach to state
management; as such, modifying a value requires a bit more verbosity.
Agent.get_and_update
leverages an Agent process for state management to update
the value and return it in one operation, similar to using the assignment as an
expression when the language is not immutable-first.
Scheme
Tony Mishler “got a little wild” and decided to knock off some dust around his experience with Scheme with his third (and final) entry. His answer here is as follows:
(define CreateCounter (lambda ()
(let ((i 0))
(lambda ()
(set! i (+ i 1))
i))))
While Scheme uses a “prefix” notation for math (+ i 1
), it gives some really
cool flexibility by treating the +
binary operator just as any other function.
Honestly, I’m impressed to see a scheme sample without a single car
or cdr
.
Other than that, I’m fascinated that it looks fairly similar to Andrew’s
“cryptic” JavaScript answer, just with most details flipped around.
Thanks to all our participants!
Thanks to so much of the team (Andrew Owen, Aaron White, Tony Mishler, Megan Kossa, Kris Henderson, Ben Cohen-Chen, and Justin Rodriguez) for their contributions this week! (Names are in timeline order of their first entry, though Aaron and Tony submitted their entries within seconds of each other, so I can’t be sure who was actually first…)
Thanks for reading, and I hope everyone learned something - I know I did!