What is programming ?
The complicated way
The textbook to understand programming is "Structure and Interpretation of Computer Programs" by Harold Abelson and Gerald Jay Sussman.
Now, I must warn you. The content of SICP is academic and the choosen language of implementation (Scheme language) is not what I would recommend to follow, especially in the context of what we are trying to achieve : a small, fast and easy to understand language. Instead, I advise to learn from it and discard what you don't need, which is sadly, almost everything. The reason is we can achieve the same functionality more easily and with much better performance.
The biggest problem with Lisp/Haskell is mathematicians trying to make the machine think like they do. It's just not going to happen. Accept the machine as it is, and find a good compromise to work with it rather than build an abstract representation of a solution that is inefficient to execute, and generate a ton of temporary results that requires garbage collection, and complex optimization.
People always talk about the sufficiently smart compiler. If we had a good compiler, working with this model would not be a problem. But why use an inefficient model in the first place ?
The simple way
Programming is simply using a computer to solve a problem or have fun playing god. The real question is what do I need to describe those operations to the machine ?
A cell is a group of bits, with an address and a value. As the most basic element, it is the "word size" of the architecture (32 or 64 bits nowadays).
A name or symbol provides a useful abstraction to refer to a piece of code or data. It's more memorable than dealing with its concrete representation (number/address).
A code block, subroutine or procedure is composed of a sequence of primitive instructions describing the work that needs to be done.
A data block usually serves as input/output to the code that must be executed. Data is typically mutable whereas code usually isn't.
Those are only broad strokes. As you'll see, the distinction between code and data is arbritary. A homoiconic language like Lisp makes no distinction between code and data, but there is a serious performance and complexity price to pay for this luxury. Even dynamic optimizers such as native JIT compilers do not always make sense. Consider the fact that their existence is justified by giving up performance in the design phase of the programming language.
The powerful concepts that must be understood:
- composition: how to group things (arrays, procedures)
- abstration: how to generalize similarities in structure or behavior (lists/stacks, high-level functions)
- sequence: what is the next thing to do (statement, expression, continuation)
- selection: what to do depending on some criteria (if, else, case)
- iteration: do something a number of times (for) or until a condition is met (while)
That is all you need to create a control language. An application language is what you create to describe your solution. The control language is merely the fundation upon which you build the application components.
Your complete application looks like a tree:
- the primitives are the roots
- the control language is the trunk
- the application language make up are the branches, leaves, flowers