In lazy evaluation , we introduced the concept of "lazy list", this concept is actually part of the native support Python
This is popular with novice troubled generator and iterator up. But before, we must first review the function of the list.
From two-tuple to list
First, we can use \(\lambda\) calculus to define a two-element tuple, or pair
:
pair
: \(\lambda a b f.f a b\)first
: \(\lambda p. p(\lambda a b. a)\)second
: \(\lambda p. p(\lambda a b.b)\)
The specific implementation is as follows:
pair = lambda a: lambda b: lambda f: f(a)(b)
first = lambda p: p(lambda a: lambda b: a)
second = lambda p: p(lambda a: lambda b: b)
We can define the test:
>>> p = pair(1)(2)
>>> first(p)
1
>>> second(p)
2
Of course, with pair
, it is not difficult to define a list, that is, the following combination is good (we still use the python
comes with 0616fb775ddd2c):
(1, (2, 3, (4, ()))))
tuples and class / type to define the list in the following chapters. But in this article, let's go back to the python
concept of 0616fb775ddd59 before to see how functional programming handles the traversal problem.
List operation
List operation is an important concept of functional programming. In real time, it implements traversal of a linear result through recursion. For example, the following C-style code:
ls = [1, 2, 3, 4]
for i in range(0, len(ls)):
ls[i] = ls[i] + 1
Here there were two effects, one i
increment, and the other is ls
situ operation. Moreover, they also use the concept of variable Of course, there is nothing wrong with this way of writing, and maintainability is acceptable, which can be regarded as a tolerable side effect. Of course, our simplest implementation is equivalent to everyone knows that it is a list expression (of course, in fact, it still has side effects):
[i + 1 for i in ls]
Of course, most people have also seen the complete operation of list expressions, which can bring their own filters:
[i + 1 for in in ls if i % 2 == 0]
This is the simplest operation of functional programming to traverse data. Of course, they also have names, map
and filter
. In Python
, they return iterable objects (we can call list
convert to list ):
map(lambda x: x + 1, ls) # [i + 1 for i in ls]
filter(lambda x: x % 2 == 0, ls) # [i for i in ls if x % 2 == 0]
Another commonly used list operation is reduce
, which plays a role of aggregation. As long as we define a binary operation , the list can be merged from the beginning to the end aggregation operation.
reduce
operation view is the process of summarizing values after traversal. For example, we want to achieve ls
. In general procedural programming, we will use the following method:
res = 0
for i in ls:
res += i # 或者和下面更类似的写法 res = res + i
However, using reduce
, we only need the following code to complete.
from functools import reduce
reduce(lambda x: x + y, ls)
The specific calculation process is as follows:
- Get
ls
first value1
and second value2
, appliedlambda x, y: x + y
, to give3
. - Get
ls
third value3
, the first step in applying the results of3
andlambda
get6
. - Get
ls
third value4
, apply the results of the second6
andlambda
get10
- The calculation is completed and the result is returned.
But, in fact, if you look at Python
of reduce
function parameters, we find that it can be brought into the initial value, the initial value when brought in all kinds of functional statements, usually called it fold_left
/ foldl
function. The effect of this with or without the initial value will be much different. The first one is to deal with the problem that the list is empty:
reduce(lambda x, y: x + y, []) # 报错
reduce(lambda x, y: x + y, [], 0) # return 0
We can even correspond this to the various elements of the previous procedural programming. 0
equivalent to res = 0
, and lambda x, y: x + y
is res = res + i
. But, in fact, foldl
than reduce
more powerful level, that the operation itself can involve different types. If we use the type flag, we will find that reduce
function itself can only be Callable[[S, S], S]
/ (S, S) -> S
, but in fact, in many scenarios, what we need is a type replacement. for example:
[1, 2, 3, 4]
=>"1234"
[1, 2, 3, 4]
=>[[1], [2], [3], [4]]
- ...
If you simply use reduce
we can not operate this relates to type conversion, foldl
into binary arithmetic type annotation is Callable[[S, T], S]
/ (S, T) -> S
. This allows us to achieve this by setting an initial value of another type. For example, in the above example of converting to a string, we can easily find the following binary operations (note the order):
lambda x, y: x + str(y)
The initial value only needs to set an empty ""
string, which is achieved as follows (try to implement [1, 2, 3, 4]
=> [[1], [2], [3], [4]]
!):
reduce(lambda x, y: x + str(y), ls, "")
Summarize
In this article, we reviewed the Python
, and introduced functional programming to implement common data traversal problems in procedural styles through list expressions/list operations to avoid the inevitable side effects in for
/ while
Next, we will use pair
to implement a list from scratch, and then we will enter the concept of a formal lazy list to see how lazy lists deal with such problems, and use functional thinking about the concepts of streaming and threading.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。