Functional Options

Posted on November 7, 2018

A while ago I read about functional options pattern in Go and then immediately forgot about it. But today I actually came across this pattern at work (when using alexcesaro’s statsd library) today. And it made me remember this rather neat pattern.

Here is a really nice article explaining them in depth. I’ll just do a quick overview before diving into funky things in Python.

Functional Options 101

Functional options are a kind-of “reverse” builder pattern. Instead of having a builder and doing things to it, we provide the steps (as values) to the builder.

Let’s look at an example. We want to produce this config

but we want default values, ability to compose together partial configurations, maybe some sanity checking.

The main trick is to express the configuration steps as functions - hence functional options. Functions that get the reference to a config and do things to it.

But we don’t let the user write this function themselves (well, maybe we could) but instead we provide specific functions.

E.g. you can only set foo via Fooish (imagine this means something)

But we let you specify an arbitrary value for bar.

Notice we could do abritrary things to bar inside Bar?

Now to consume it we just need a starting config and then we apply the option steps to it.

Looking contrived? All the hard work was so we can get this very nice and easy to use API.

Abusing them in python

Can we do the same thing in python? Sure.

we just lose the type safety. And we cannot limit the user to just use the functions we provide.

But if we can use this pattern we can also abuse it. Here’s a keyword-arg imitation (complete with default values, can you spot them?)

Why would you ever do this? Honestly…I don’t know. Maybe if you have complex configuration where a single flag should trigger multiple things. But it’s an interesting pattern that work around the lack of Go’s keyword arguments in a nice way.

Facebook Twitter Google Digg Reddit LinkedIn StumbleUpon Email
comments powered by Disqus