My grandson has recently learned to count, so I made a set of cards we could ‘play numbers’ with.
We both played. I showed him that you could write ‘maths sentences’ with the ‘and’ and the ‘is’ cards. Next time I visited, he searched in my bag and found the box of numbers. He emptied them out onto the sofa and completely unprompted, ‘wrote’:
I was ‘quite surprised’. We wrote a few more equations using small integers until one added to 8, then he remembered he had a train track that could be made into a figure-of-8 , so ‘Arithmetic Time’ was over but we squeezed in a bit of introductory set theory while tidying the numbers away.
From here on, I’m going to talk about computer programming. I won’t be explaining any jargon I use, so if you want to leave now, I won’t be offended.
I don’t want to take my grandson too far with mathematics in case it conflicts with what he will be taught at school. If schools teach computer programming, it will probably be Python and I gave up on Python.
Instead, I’ve been learning functional programming in the Clojure dialect of Lisp. I’ve been thinking for a while that it woud be much easier to learn functional programming if you didn’t already know imperative programming. There’s a famous text, known as ‘SICP’ or ‘The Wizard Book’ that compares Lisps with magic. What if I took on a sourceror’s apprentice to give me an incentive to learn faster? I need to grab him “to the age of 5”, before the Pythonista get him.
When I think about conventional programming, I make diagrams, and I’ve used Unified Modelling Language (UML) for business analysis, to model ‘data processing’ systems. An interesting feature of LIsps is that process is represented as functions and functions are a special type of data. UML is designed for Object Orient Programming. I haven’t found a way to make it work for Functional Programming (FP.)
So, how can I introduce the ideas of FP to a child who can’t read yet?
There’s a mathematical convention to represent a function as a ‘black-box machine’ with a hopper at the top where you pour in the values and an outlet at the bottom where the answer value flows out. My first thought was to make an ‘add function’ machine but Clojure “treats functions as first-class citizens”, so I’m going to try passing “+” in as a function, along the dotted line labelled f(). Here’s my first prototype machine, passed 3 parameters: 2, 1 and the function +, to configure the black box as an adding machine.
In a Lisp, “2 + 1” is written “(+ 2 1)”.
The ‘parens’ are ‘the black box’.
Now, we’ve made our ‘black box’ an adder, we pass in the integers 2 and 1 and they are transformed by the function into the integer 3.
We can do the same thing in Clojure. Lisp parentheses provide ‘the black box’ and the first argument is the function to use. Other arguments are the numbers to add.
We’ll start the Clojure ‘Read Evaluate Print Loop’ (REPL) now. Clojure now runs well from the command line of a Raspberry Pi 4 or 400 running Raspberry Pi OS.
user=> (+ 2 1)
Clearly, we have a simple, working Functional Program but another thing about functions is that they can be ‘composed’ into a ‘pipeline’, so we can set up a production line of functional machines, with the second function taking the output of the first function as one of it’s inputs. Using the only function we have so far:
In Clojure, we could write that explicitly as a pipeline, to work just like the diagram
(-> (+ 1 2) (+ 1))
or use the more conventional Lisp format (start evaluation at the innermost parens)
(+ (+ 1 2) 1)
However, unlike the arithmetic “+” operator, the Clojure “+” function can
add up more than 2 numbers, so we didn’t really need to compose the two “+” functions. This single function call would have got the job done:
(+ 1 2 1)
SImilarly, we didn’t need to use 2 cardboard black-boxes. We could just pour all the values we wanted adding up into the hopper of the first.
Clojure can handle an infinite number of values, for as long as the computer can, but I don’t think I’ll tell my grandson about infinity until he’s at least 4.