Jun 01, 2021 Article blog
1. It's all about eliminating side effects
2. Functional programming is not just map and reduce
3. Functional programming is getting stronger in some programming languages
Today, let's talk about the little knowledge
函数式编程
函数式编程
has been around for more than 60 years, but so far it's been small.
Only game-changing businesses like
Google
rely on
函数式编程
which ordinary programmers know little about.
That will soon change.
Languages like
Java
and
Python
are increasingly
函数编程
and new languages like
Haskell
are fully integrated into
函数式编程
Simply put,
函数式编程
is building functions for immutable variables.
Instead, object-oriented programming is about having a relatively fixed set of functions, and we're mainly modifying or adding new variables.
函数式编程
has features that are ideal for demand tasks such as data analysis and machine learning. B
ut that doesn't mean we should move away from
面向对象编程
and use
函数式编程
entirely.
We need to understand the rationale so that we can use them in due course.
(Recommended Tutorial: Fool Function Programming)
To understand functional programming, we need to understand functions first. It may sound boring, but in short, it's insightful.
Simply put, a function is something that converts input into output. I
t's just that it's not that simple.
Consider the meaning of this function in
Python
def square(x):
return x*x
This function is simple.
It requires a variable
x
which could be an
int
or a
float
or
double
and then output the square of the variable.
Think again about this function:
global_list = []
def append_to_list(x):
global_list.append(x)
At first glance, this function accepts a variable
x
which returns nothing, regardless of type, because there is no
return
statement.
Is that really the case?
If the
global_list
is not defined in advance, the function will not work and its output will be the same list, albeit modified.
Although
global_list
does not declare input, it changes when we use the function:
append_to_list(1)
append_to_list(2)
global_list
It returns a
[1,2]
not an empty list.
This may be the problem, and the list is indeed an input to the function, although we have not specified it explicitly.
These implied inputs, or other outputs in other cases, have an official name: side effects. Although we have given only one simple example, in more complex procedures, these may make us face real difficulties.
Think about how to test
append_to_list
Not only do we need to read the first line and test the function with any
x
but we also need to read the entire definition to understand what it does, define
global_list
and test it in this way.
This example tells us that when you're working on a program with thousands of lines of code, simple things quickly become boring.
The good news is that there is a simple solution: be honest about what the function is as input. This is better:
newlist = []
def append_to_list2(x, some_list):
some_list.append(x)
append_to_list2(1,newlist)
append_to_list2(2,newlist)
newlist
We didn't make much of a change, the output was still
[1,2]
and everything else remained the same.
However, we have changed one thing: the code now has no side effects.
Now, when we look at the function declaration, we know exactly what happened. If the program isn't working properly, we can also easily test each feature individually and find out which one is in trouble.
Functions with explicitly declared inputs and outputs are functions that have no side effects, and functions that do not have side effects are pure functions.
A very simple definition of function programming is to write programs only with pure functions. Pure functions never modify variables, only create new variables as output.
In addition, for a given input of pure functions, we can get a specific output. I nstead, impure functions may depend on some global variables. T herefore, if the global variables are different, the same input variables may result in different outputs. The latter can make debugging and code maintenance more difficult.
Here's a simple rule that can easily detect side effects: since each function must have some kind of input and output, function declarations without any input or output must be impure. This is the first declaration you might want to change if you are functionally programmed.
Loops are not something in functional programming.
First, let's think about the following
Python
loop:
integers = [1,2,3,4,5,6]
odd_ints = []
squared_odds = []
total = 0
for i in integers:
if i%2 ==1
odd_ints.append(i)
for i in odd_ints:
squared_odds.append(i*i)
for i in squared_odds:
total += i
The above code is significantly longer than the simple operation we're going to do. And it doesn't work because we're modifying global variables.
Instead, we can replace it with the following code:
from functools import reduce
integers = [1,2,3,4,5,6]
odd_ints = filter(lambda n: n % 2 == 1, integers)
squared_odds = map(lambda n: n * n, odd_ints)
total = reduce(lambda acc, n: acc + n, squared_odds)
This is a complete function. I
t's shorter and faster because we don't need to iterate too many array elements.
If you understand how
filter
map
and
reduce
work, the code is not hard to understand.
This does not mean that all function code uses
map
reduce
and so on. T
his does not mean that you need functional programming to understand
map
and
reduce
It's just that when you abstract loops, these functions pop up a lot.
When it comes to the history of functional programming, many people start with the invention of
lambda
functions.
Although
lambda
is undoubtedly the cornerstone of functional programming, they are not the root cause.
Lambda
functions are tools that you can use to make programs work.
However, we can also use
lambda
in object-oriented programming.
Although the example above is not static, it is still functional.
Even if static types add an extra layer of security to our code, their functions are not essential. However, this may be a good addition.
Perl
treats side effects differently from most programming languages. I
t contains a magic parameter
$\
Perl
does have its advantages, but I don't use it for functional programming.
(Recommended tutorial: Perl tutorial)
If you're functional programming with
Java
I can only wish you luck.
Because half of your programs are made up of static keywords, other
Java
developers will treat your program as a disgrace.
This is not to say how bad
Java
is, but because it is not designed to solve problems with functional programming, such as database management or machine learning applications.
(Recommended tutorial: Java tutorial)
Interestingly:
Scala
goal is to unify object-oriented and functional programming.
If you think it's a little strange, you're not alone, because everyone thinks so: the goal of functional programming is to eliminate side effects altogether, while object-oriented programming is to keep the side effects inside the object.
Still, many developers see
Scala
a language that helps them transition from object-oriented programming to functional programming.
Perhaps in the next few years, they will be easier to fully function.
(Recommended tutorial: Scala tutorial)
Python
encourages functional programming. O
ne fact is that each function has at least one input
self
by default.
It's a lot like
Python
Zen: explicit is better than implicit!
(Recommended tutorial: python tutorial)
According to its creators, about 80% of
Clojure
is functional programming. B
y default, all values are immutable, just as they are needed in functional programming. H
owever, we can solve this problem by using a variable value wrapper around these immutable values.
When you open such a package, what you get is the same.
(Recommended tutorial: Clojure tutorial)
This is one of the few languages of purely functional and static types. W
hile this may seem like a time consumer during development,
Haskell
can pay a heavy price when debugging programs.
It's not as easy to learn as other languages, but it's definitely worth investing in!
(Recommended tutorial: Real World Haskell Chinese)
Functional programming is still a newborn compared to object-oriented programming.
But if the inclusion of functional programming principles in
Python
and other languages has a different meaning, then functional programming is likely to gain attention.
Functional programming is useful for large databases, parallel programming, and machine learning. All of this has flourished over the past decade.
Although object-oriented code has inestimable advantages, the advantages of function code can not be ignored. Just learning a few basic principles is enough to make us a developer and prepare for the future.
The above is about functional programming related to the introduction, I hope to help you.