abstract machine models
equivalent models
turing machine
lambda calculus
imperative
procedural
declarative
functional
object-oriented
C, Go
Smalltalk, Java
Models of Computation
typed
untyped
Lisp family
Haskell, ML
abstract machine models
equivalent models
turing machine
lambda calculus
imperative
procedural
declarative
functional
object-oriented
C, Go
Smalltalk, Java
models of computation
typed
untyped
Lisp family
Haskell, ML
"...expresses the logic of a computation without describing its control flow."
Lloyd, J.W., Practical Advantages of Declarative Programming
Uses statements that change a program's state and rely on explicit control flow.
(describes what to do)
(tells how to do it)
The greatest barrier to entry in math and science is its vocabulary...
-- someone famous, maybe
Applying the function to an argument (a value in its domain), so that we can get the output.
The number of arguments or operands that a function takes. A function can be unary (arity of 1), binary (arity of 2), etc.
A pure function is one that does not depend on any external state that could change during execution (always returns the same output given the same input) and does not cause any side-effects, like mutation of a global variable.
A side effect is any change to the state of the system or any kind of interaction with the outside world that we can see. An example of the former is updating an HTTP request object and an example of the latter is printing to standard output.
Application State
Input/Output
writes/passes
reads/accepts
Can I replace this function with its return value without changing how my program behaves?
A closure is a function defined inside of another function definition that has access to that outer function's environment. It's a useful technique for binding together the data and the operation and in a sense, a closure is like a record that stores these two things for later use.
Any function definition that is not bound to an identifier. Usually, we use these as arguments to higher-order functions or for creating a return value from a higher-order function that needs to return a function. In lambda calculus, all functions are anonymous.
A language supports first-class functions if it allows you to pass a function as an argument to another function, return a function as a value from another function, and store functions inside of variables and data structures.
Generally, a higher-order function is one that either accepts another function as an argument, returns a function as its result or both of these. The concept of a higher-order function makes function composition possible.
Lets us take simple functions and compose them into more complex functions. We can do this because our functions have referential transparency. This makes it incredibly easy to model our programs and reason about what they're doing.
When we take a function and bind one or more of the arguments to a specific value in order to produce a function of a smaller arity, we're partially applying that function.
When we take a function that has an arity greater than 1 and produce a series of nested functions, each with an arity of 1, we are currying. A curried function always returns either a function that takes one argument (a unary function) or the result of applying all arguments through all of the nested functions, one at a time.
Discrete Mathematics with Applications, 4th Edition, by Susanna S. Epp
Discrete Mathematics and Functional Programming, by Thomas Van Drunen
An Introduction to Functional Programming Through Lambda Calculus, by Greg Michaelson
Category Theory for the Sciences, by David I. Spivak