Why does Nengo have it's own parameter type-checking system?

Nengo has it’s own parameter system which is a way of enforcing strong typing. There are many different libraries available to accomplish this, but we decided to roll our own. Why?

I ask this question to Terry literally every 4 months, so I thought I would ask the question here to get a canonical response.

The parameter system does quite a bit more than enforce types; see for example all the validation we do on connections. If we used an external parameter system, we would still have to write those custom validation and coercion routines, so using an external library wouldn’t save us all that much code. Since it exists, the maintenance burden of the params system is pretty small – smaller, I would argue, than the effort to keep up with changes in an external library. The usual argument to use an external library is that many other people know it already, so by switching to it we have access to a new set of capable programmers. But I’m no aware of any parameter system in Python that’s got a large user base and is used in many projects.

Historically, one of the very early goals of Nengo was to have minimal dependencies in order to be easy to install. Scientific software is notoriously hard to install, and if a user has an issue installing Nengo they’re pretty likely to never use it and to have a negative opinion of it. So, there was (and still is) a concerted effort to have no dependencies other than NumPy. Unfortunately NumPy is still not as easy to install as would be ideal, but I don’t think I’ve ever had anyone be able to install NumPy but not Nengo. So, adding a new non-NumPy dependency is a relatively big deal.

Additionally, back when we made the parameter system, the only analogous thing that I was aware of was traits, which at the time seemed to be tightly coupled to Enthought’s GUI stuff, which would be a huge headache to depend on. There’s now traitlets, which at the time was still part of the huge IPython codebase, which would also be a pain to depend on for core functionality.

Things are quite a bit different now than; traitlets is a separate independent package, and pip solves a lot of the problems there used to be in Python packaging. However, with a lot of these things that are there now for what seem like historical reasons, there have to be pretty compelling reasons to switch. Nengo’s out in the wild now and people might be depending on implementation details that are difficult or impossible to replicate in an external parameter library. From what I know that’s out there right now, I haven’t seen any compelling reasons to switch, but I’m happy to evaluate any new libraries if anyone has suggestions.

One closing thought (which probably applies more to the JavaScript community than Python, but that’s where I’ve been living lately) is that you should be suspicious of problems that have a ton of solutions but no clear front-runner. Yes, there are a lot of Python libraries out there to do something like what we do in nengo/params.py, but it’s very likely that none of them do it in quite the same way because our needs are subtly different than the project that spawned that library. Meanwhile, nengo/params.py is only around 500 lines of Python, much of which is specific to Nengo-esque things (like handling NumPy arrays well, and enabling immutable objects). It’s a problem that is small enough to be solvable by many people, but complex enough that no solution will handle all use cases well.

2 Likes

We also allow to copy and pickle Nengo object now and those might be functionalities not supported by other type-checking libraries.