Functional programming is a tricky beast but I am finding it unexpectedly liberating. Here's an example that might help you make progress too.
Suddenly the benefits of functional programming (FP) seemed well worth investigating properly.
I read a couple books (this one and another), plus a few Medium and DEV articles. Then took a more direct step and went through this whole Udemy course. I must admit to skipping some of the later exercises - I find it really tough to focus sufficiently on problems for their own sake. Need a real issue to implement!
So it was lucky that I was in the latter stages of developing an app which has a very data hungry modal dialog (not yet in production release, will try to update later with a link). So I built this using the framework applied in the Udemy course - and it was very liberating. The framework isn't React but has similarities, with virtual DOM, data driven state, protection from mutation, clean event loops and complex UI that is easy to update or extend.
After the reading and the course, did I really think I'd "got" it? By which I mean the fundamental reasoning and problem solving concepts - things like:
- no data mutation
- pure functions
Understanding these in principle is fine, but it takes practice, as for any code reasoning, to re-configure your problem solving processes.
The data mutation thing I got first, although it is tightly linked to the concept of pure functions:
- Keep functions simple
- Think in terms of individual functional steps rather than integrated bundles of logic
- Return new versions of your data
- Make sure to avoid library functions which mutate the passed-in data (e.g.
I can't say my code is perfect in these regards but I think I'm doing OK at knowing when there is a problem and whether I care.
for loops has been the trickiest. Recursion has always filled me with dread and examples of
reduce() are typically quite simple. They give you the technical syntax but not really the reasoning process you need in order to actually use them.
This morning I did a rare thing and shouted "Yes! OMG it actually worked!" when a piece of refactored code worked the first time. A joyous occasion. I won't claim that the refactor is perfect FP but for me the diff is instructive - hope you find it so as well.
The code below is training a neural network (using Brain.js) and returning some test results to a web page. In the
try block, the CSV data file is processed (get the training and test data) followed by returning the results via the
res object. I used a
forEach loop to iterate through the CSV data, responding according to need with some nested if/else control logic.
So I started with this procedural tangle:
Which I turned into the following, whilst also adding some additional logic to analyse the neural network (a bit). The long
ifstatement in the
parser()function has been simplified to a few lines, kicking off a recursive function. I also replaced the two
forEachloops which processed the raw training and test data with functions
map(). Finally, the new functionality
identifySignificantInputs()I added to process the network's weights uses a
map()to iterate (or map) through the hidden nodes and sum up (or reduce) each node's set of weights.
Now I just need to write it this way first time rather than with a re-factor!
For reference, here is the (edited for brevity) neural network definition object that contains the weights.