When understanding programming language features, and explaining them to others, I’ve found it useful to have two different kinds of explanations.
The first kind, which I call an operational explanation, explains a feature in terms of how the program executes.
The second kind, which I call a denotational explanation, explains features in terms of what they mean to the programmer.
For myself, and those I teach, it’s usually easier to start with an operational explanation. However, I find denotational explanations more useful in the long term.
Let’s start with an example: the humble function. As a thought experiment, think about how you would explain functions to a new programmer.
I would probably say something like “a function allows us to reuse an expression in different contexts where parts of that expression can change”.
This is a very abstract definition, so I’d quickly follow up with an example and then walk through the process of evaluating