The power of functional thinking comes from mathematics. Mathematical functions have many features-functional languages try to emulate the real world.
So in the beginning, we start with a 加1函数
:
ADD1 (x) = X+1
What does that mean? Well, it looks pretty straightforward. It means that there is an operation that starts with a number and then adds 1 to it.
We introduce some terms:
A collection of values that can be entered as a function is called domain. In this way, it may be a real collection, and for simplicity we are limited to integers.
The set of values that can be output by a function is called a range (more scientifically, it should be called the codomain image). is still limited to integers only.
The function is referred to as mapping domain to range.
In F #, we define this:
Let add1 x = x + 1
If you enter in the F # Interactive window, you can see the result (signature of the function):
Val Add1:int-INT
Take a closer look at the output:
The general meaning is: The function add1 maps an integer of domain to an integer in range
ADD1 is defined as shorthand for val,value. We'll discuss value in a moment.
Arrows are ->
used to display domain and range. Here, domain is the int type, and range is the int type.
Note that the type is not specific, the F # compiler guesses that the function is using Int.
Key properties of mathematical functions
Mathematical functions have many properties that differ from the functions you use in procedural programming.
This mathematics provides a lot of powerful benefits, so functional programming languages are also trying to enforce these properties at design time. We look at them in turn.
The function will give you the same output for the given input value.
In imperative programming, we think that functions do things or calculate things. The math function doesn't do any calculations-it simply maps the input to the output. In fact, another way to think about defining a function is simply as a collection of all the mappings. For example, define the ADD1 function in a very blunt way (in C #):
int add1 (int input) {switch (input) {case 0:return 1; Case 1:return 2; Case 2:return 3; Case 3:return 4; etc ad infinitum}}
Obviously, we can't set a case for every possible integer, but the principle is the same. You can see absolutely no calculation, just a traversal.
function has no negative effect
In mathematical functions, input and output are logically two different things, and they are all pre-defined. The function does not alter the input and output-it is simply an existing output value from the domain mapping of the existing input values to the range.
In other words, the function is not likely to have any effect on the input. The function does not actually calculate or manipulate anything, it is merely a beautified traversal.
The invariance of values is subtle but very important. If I'm doing calculations, I don't expect numbers to change it, when I add them together. For example, if I have:
x = 5y = x+1
I don't expect to add 1 after X is changed. I would expect to get a different number Y, while X is not touched. In the mathematical world, integers already exist in an immutable set, and the ADD1 function simply defines the relationship between them.
The ability of the pure function
This function has repeated results, and there is no negative effect, which we call the pure function. You can use them to do a lot of interesting things:
They are simple to parallel. I can take all 1 to 1000 integers, say, given 1000 different CPUs, I can make them execute the ADD1 function at the corresponding integer value at the same time. This is safe because there is no need for any interaction between them. No need to lock, mutex,semaphore and so on.
I can use the function lazily, only to execute it when I need the output. I can be sure the results will be the same, whether I'm doing it now or later.
I just need to execute a function for a specific input and then cache the result because I know that the same input always corresponds to the same output.
If I have a lot of pure functions, I can execute them in the way I like. Again, it will not change the end result.
You see, if we can create a functional programming language, we can get a lot of powerful technology right away. It is true that you can do these things in F #.
Unhelpful properties of mathematical functions
Input and output cannot be changed
A theoretically unchanging value may seem like a good idea, but if you can't assign a variable to a value in the traditional way, how do you get the job done?
I make sure that you're not a problem as you might think. When you finish this series, you'll see how it's actually solved.
Mathematical functions often have only one input and output
As you can see from the chart, mathematical functions often have only one output. That's true, although it's not so obvious when you first see them.
It seems to be a big annoyance. How can you do useful things without more parameters?
There's a way to do it, and it's completely transparent to you in F #. It is called "currying".
In fact, you'll see later that these two "unhelpful" properties will prove incredibly useful--and a key part of what makes the math function very powerful.
? Mathematical functions--the power behind functional programming