The core idea of functional programming

Functional programming has become more and more popular in recent years. Languages ​​with functional programming despise languages ​​without functional programming, and languages ​​with pure functional programming despise languages ​​that are not pure functional programming.

So, what exactly is functional programming, and what is the core idea of ​​functional programming?

The first feature of functional programming is that you can pass a function as a parameter to another function, which is the so-called higher-order function. For example, to sort an array, you can pass in a sorting function as a parameter:

String[] array = {"orange", "Pear", "Apple" };
Arrays.sort(array, String::compareToIgnoreCase);
The second feature of functional programming is that it can return a function, so that it can be closed Package or lazy calculation:

The above two features only simplify the code. In terms of code maintainability, the biggest advantage of functional programming is referential transparency, that is, the result of function execution depends only on the input parameters and not on the external state. Therefore, we often say that functional programming has no side effects.

No side effects have a huge advantage, that is, the function is stateless inside, that is, the input is certain, and the output is certain, which is easy to test and maintain.

Many beginners tend to struggle with "pure" functional languages, thinking that only Haskell, a language that eliminates variables and side effects, is authentic functional programming. Some people even think that pure functions cannot have any IO operations, including logging.

In fact, this kind of entanglement is meaningless, because the bottom of the computer is a completely variable memory and unpredictable input system. The pursuit of perfection without side effects is unrealistic. We only need to understand the idea of ​​functional programming and do business logic. When it comes to "no side effects", as for the insignificant "side effects" such as variables, logging, and read cache, there is no need to worry at all, there is no need to solve it, and it is almost impossible to solve it.

Let's give a chestnut.

For example, a financial software needs a function to calculate personal income tax. The input is an IncomeRecord, and the output is a tax amount:

double calculateIncomeTax(IncomeRecord record) { } Assume that IncomeRecord looks like this:


class IncomeRecord { String id; // ID Number String name; // Name double salary; // Salary } First of all, we don’t consider the messy things like five social insurance and one housing fund. We only pay attention to how to calculate the tax. For simplification, we assume that the calculation is calculated at 20% after directly deducting an exemption amount:




double calculateIncomeTax(IncomeRecord record) { double threshold = 3500; double tax = record.salary <= threshold? 0: (record.salary-threshold) * 0.2; return tax; }The above program was before September 1, 2018 No problem. The problem is that the threshold has been adjusted to 5000 after September 1, 2018. The calculation results should be different in August 2018 and September 2018. How to change?




Ordinary developers’ reforms: Isn’t that simple? Get the current date directly and return the correct threshold:

double calculateIncomeTax(IncomeRecord record) {
double threshold = today() < date(2018, 9, 1) ? 3500 : 5000;
double tax = record.salary <= threshold ? 0 : (record.salary - threshold) * 0.2;
return tax;
}
程序是没错,问题是:

The same input, running on August 31, and running on September 1, the results are different, should the accountant do the August payroll on September 1, must the computer time be adjusted to August?

Think about it from the perspective of functional programming, and you will find the problem:

Today() this function, the return result is related to time, which makes calculateIncomeTax() no longer a pure function, it is related to the current time.

Then how to restore calculateIncomeTax() to a pure function while supporting the threshold adjustment?

The method is to pass in time-related variables as parameters. For example, add several fields to IncomeRecord:

class IncomeRecord { String id; // ID number String name; // name double salary; // salary int year; // year int month; // month } This way we can eliminate the today() call:






double calculateIncomeTax(IncomeRecord record) { double threshold = date(record.year, record.month) <date(2018, 9)? 3500: 5000; double tax = record.salary <= threshold? 0: (record.salary-threshold ) * 0.2; return tax; } calculateIncomeTax() has become a pure function again, and accounting does not need to change the computer time.




Do you think this example is too simple? In fact, if simple functions can be written as stateful, then complex business logic must be written into a pot of porridge.

Give a complicated chestnut:

For a stock trading system, if we define the input as: the cash and shareholdings of all shareholders before the market opens, and all orders during the trading period, then the output is the cash and shareholdings of all shareholders after the market closes:

StockStatus process(StockStatus old, List orders) { for (Order order: orders) { sendExchangeResult(…); // Send information to each transaction } } Obviously this is a pure function, although in the process , This function will send various heartbeat messages to investors' friends.







If the model of the trading system is designed as such a pure function, then in theory we only need to process all orders from the day the stock market opens, and then we can correctly get the status after the closing of today.

In other words, as long as you take a backup of the system status before the opening of any day (that is, the backup of the entire database), and reprocess the order of the day, you will get the status of the closing of the day. This process can be done any number of times, and the result remains the same. Therefore, it is very suitable for verifying whether the modification of the code affects the business process.

So the question is, how to deal with the countless time-related states in the trading system into pure functions? The processing of this model is much more complicated than calculating a tax.

This is the essence of functional programming: the business system model is stateless. The quality of the model directly affects the correctness, reliability, and stability of the code, and whether 996 is required

Guess you like

Origin blog.csdn.net/qq_45424679/article/details/115104439