The purpose of this blog was originally to discuss data (indicated by \(\tau\)) and functional programming/computer science (indicated by \(\lambda\)). But in fact, this blog hasn't written anything about functional programming , which seems a bit "unjustified". In recent years, in some projects and in my own theoretical study, I have gained some insights into functional programming. I hope to use this series to pass on some very useful methods of functional programming, and to urge myself to think and learn in this area.
Of course, there are good blogs/articles or books that introduce functional programming. However, because Python
's support for functional programming is not very good (such as recursive acceleration), so the Python
implementing functional programming with 0614bd8e73e5d2 are often based on functools
, itertools
and some recursive concepts. So this blog series tries to make up for the shortcomings in this area, and expands our horizons, allowing us to add in the content of philosophy, categorization and other fields, and further "meta" thinking about programming itself.
What is a function
Of course, as the first article in this series, we are going to discuss the concept of "no side effects".
First of all, we have to return to a thought, that is, what is the concept of Python
of function(s)
function best discussion is of course Fraser, the pioneer of analytical philosophy (for details, please refer to the following quote). But we abstracted it concretely, the mathematical function has a clear definition, that is, "an independent variable is mapped to the only dependent variable." In other words, the function repeatedly brings the same value, so the result should be consistent. For example, let's take the following example, no matter how many times we bring in x = 1
we can return the result of 2
def f(x):
return x + 1
There are also books (such as the Functional Programming in Scala mentioned in the quote) that also express this principle as the "symbol substitution principle", that is, we can use the equation of declaring function to substitute into the following formula. This is also an extended example of judging whether it is a function, for example:
def f(x):
return x + 1
def g(x):
return f(x) ** 2
In this example, we can use the following substitution principle to achieve it. This is mathematically defined function best example.
def g(x):
return (x + 1) ** 2
We call the above functions that clearly conform to the mathematical definitions "no side effects", because their calculations only involve the concept of calculating themselves, and all symbols are just indicators of a certain value/function, without any other meaning. Han.
In fact, the function in Python
But in fact, Python
always allows us to define something that does not meet the above specifications, but Python
is still called a function in the term, such as the following example of a global variable:
a = 1
def f(x):
global a
a += x
return a
We brought in two x = 1
, the results of the first result is 2
, the second was 3
. This is not in line with the definition of our function, and the reason is that it changes a variable a
outside the function, so in addition to calculations, what has changed, so we say that it has "side effects".
The second reason involves variable variables. In fact, the above a
is also an example of variable variables. But the more prominent ones list
and dict
or the values of in-situ operations. For example, the following example:
def f(ls, a):
ls.append(a)
return ls
In this example, no global variables are involved, but when we bring in ls = [1, 2, 3]
and a = 1
, we still find that the return value is different every time we bring it in. We can also ls
as a side effect. If we just want to get the ls
adding an element to 0614bd8e73e779, then this problem will be very serious.
SCIP ( Structure and Interpretation of Computer Programs ), a very good overview of the differences in the processing functions of these two ideas. In the former "no side effects" example, a
and f
only have the meaning of indicating a value/function; but for the latter function with the concept of "side effects", we must construct an "environment" the concept of. In this environment, there are houses (maybe the concept of memory/CPU cache in a computer). a
and f
indicate houses (but sometimes they refer to the things in the house). What’s more terrifying is the house. The size of will also change; and in the "no side effects" example, we only need to know that the symbol always refers to one thing, and it will not change after one designation, and there is no need to change the house.
The good and bad side effects
Now, let's look at the advantages and disadvantages of "no side effects" and "side effects".
1. Backtracking issues
If a function, it must have a certain output for a certain input, which means that we can easily find the problem, locate the problem, and reproduce the problem. And if a program contains a lot of "side effects", it means that we cannot control what it modifies outside of the function, as small as a variable function and as large as a computer's environment variables. This also leads to why, many programs report error feedback, so many environmental variables, computer environment and other concepts have to be printed.
And no side effects means very strong "testability", we will list them one by one in the following articles. In addition, "property-based testing" is also possible. This means that we can control our procedures more strongly. Even for a static functional language (unfortunately Python
is not), most of the problems can be exposed and solved at the compilation stage.
2. Programs that cannot interact with the environment are actually useless with a high probability
Purely using the functional concept, what we actually construct is a logical symbol computing system. If there is no interaction with the external environment, it is a toy on the platform. We even use print
to produce a side effect of the screen outside the function. Therefore, the absence of side effects means that its application is difficult. Of course, the concept of "monads" confines the side effects to a very small range. These methods allow us to have a strong grasp of our own procedures, and also have a certain degree of "freedom of interaction." This is also the programming idea we want to emphasize in this series
3. Efficiency
In fact, in our example above, we can already see that the concept of the computer (/Turing machine) itself is based on the environment or side effects. However, if functional programming is implemented on a side-effect machine, the efficiency will drop. What's more, if we don't use append
, this means more space and the concept of copying more values. All these make the efficiency of the program greatly compromised. In addition, Python
does not have a good effect on the speed optimization of functions such as recursion, which also makes side effects more likely to be favored.
However, this concept of efficiency may be more ambiguous. If you look at functional programming from a larger perspective, there are various optimization solutions of your own, which we will introduce one by one later.
4. Expressive skills (new)
In the above discussion on "environment" and "substitution", we also found that if we use the concept of "environment" we will have many more concepts, such as "passing by value", "passing by address", "variable variable", Concepts such as "global variables", and these concepts must be endogenous in the language. In part, this is a manifestation of weak expression efficiency. In fact, functional programming only relies on the two concepts of value and function, plus basic types and operations to achieve almost everything (or Turing complete). The concepts of "recursion" and "monad" we mentioned later are "derived" rather than "endogenous" to some extent. This is more characteristic of Top-down mathematics (of course, whether mathematics is like this is another question).
An explanation about the domain
Finally, we have to mention a small question about "domain", I did not mention it in the above discussion, because we slightly used the concept of type/domain. For example, the following function (I deliberately brought type annotations):
def f(x: int) -> int:
if x > 0:
return x + 1
In this example, in fact, the value range of \(x\) can only be \(x> 0\) (although in exceptional cases Python
will output None
), but in fact this kind of operation and mathematical functions are still slightly The difference is because its domain of definition at the time of declaration is int
domain of definition is \(x \in N\). Not all values in int
In languages with better functional support such as scala
or haskell
, this function is also called Partial Function (Note that is not the as . The arguments of the domain have been declared. For example, the above function f
defined in scala will use PartialFunction
:
val f: PartialFunction[Int, Int] = {
case x if x > 0 => x + 1
}
However, in actual use, we tend to use "no side effects" to describe the basic characteristics and properties of functional programming, so this kind of detailed discussion is ignored in most occasions, but you should pay attention to mathematical expressions. one time.
References
- Zhang Cuiyuan. On Frege's "Functions and Concepts". Modern Communication 14 (2018).
- Chiusano, Paul, and Runar Bjarnason. Functional Programming in Scala. Simon and Schuster, 2014.
- Abelson, Harold, and Gerald Jay Sussman. Structure and Interpretation of Computer Programs. The MIT Press, 1996.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。