nengo/nengo — pull request #588 by tbekolay (2014-12-14 21:31:26+00:00)
Title: Refactored synapse classes

The major change here is to pull the logic from the builder to the synapse classes. This makes them accessible from other parts of the code, rather than being buried in the builder. This results in much simpler builder code also; there is no need for build methods for each synapse, unless some internal state of that synapse would like to be probed (which is still easily done if desired).

The main pattern used for this is very similar to the pattern that we use in the builder. Each `Synapse` class has a `make_filt` function that returns a function that can be repeatedly called to filter a signal. Its use is best demonstrated by `nengo.synapses.filt` and `nengo.synapses.filtfilt`, which replace the old versions in `nengo.utils.numpy`, which were specific to lowpass filters; these new functions take in an arbitrary synapse instance instead, which also removes the need for `nengo.utils.numpy.lti`.

Implementation-wise, the synapse models make heavy use of `functools.partial` as a way of binding arguments that would otherwise need to be repeatedly passed to the `filt` function. Note that these arguments can be overridden on the partial function returned, if desired. But in general, it's a somewhat cleaner and more idiomatic way to achieve what we were doing in the old build methods.

The benefits to this method, I hope, are clear from the description above and through looking at the diff. The main downside here is that we're using a pattern that may be difficult for newer programmers to understand. Basically, we have classes whose main use is to generate a function, which is what we actually care about. However, I don't think most will need to directly interact with these functions, and they'll mostly be of interest to backend designers, or a few use cases that we'll provide examples for.