|
1 | 1 | # Going functional |
2 | 2 |
|
3 | | -You get very far building your application with straight forward imperative actions. This is typically how we learn programming and is arguably close to how we think about the world. But this approach can cause you to overload your actions with imperative code, making them more difficult to read and especially reuse pieces of logic. As the complexity of your application increases you will find benefits doing some of your logic, or maybe all your logic, in a functional style. |
| 3 | +You get very far building your application with straightforward imperative actions. This is typically how we learn programming and is arguably close to how we think about the world. But this approach can cause you to overload your actions with imperative code, making them more difficult to read and especially reuse pieces of logic. As the complexity of your application increases you will find benefits to doing some of your logic, or maybe all your logic, in a functional style. |
4 | 4 |
|
5 | 5 | Let us look at a concrete example of how messy an imperative approach would be compared to a functional approach. |
6 | 6 |
|
7 | 7 | ```marksy |
8 | 8 | h(Example, { name: "guide/goingfunctional/messy" }) |
9 | 9 | ``` |
10 | 10 |
|
11 | | -What we see here is an action trying to express a search. We only want to search when the length of the query is more than 2 and we only want to trigger the search when the user has not changed the query for 200 milliseconds. |
| 11 | +What we see here is an action trying to express a search. We only want to search when the length of the query is more than 2 characters and we only want to trigger the search when the user has not changed the query for 200 milliseconds. |
12 | 12 |
|
13 | 13 | If we were to do this in a functional style it would look more like this: |
14 | 14 |
|
@@ -37,8 +37,8 @@ h(Notice, null, "Note that we give all the actual operator functions the same na |
37 | 37 |
|
38 | 38 | You might wonder why we define the operators as functions that we call. We do that for the following reasons: |
39 | 39 |
|
40 | | -1. It ensures that each composition using the operator has a unique instance of that operator. For most operators this does not matter, but for others like **debounce** it actually matters |
41 | | -2. Some operators requires options, like the **lengthGreaterThan** operator we created above. Defining all operators as functions just makes things more consistent |
| 40 | +1. It ensures that each composition using the operator has a unique instance of that operator. For most operators this does not matter, but for others like **debounce** it actually matters. |
| 41 | +2. Some operators require options, like the **lengthGreaterThan** operator we created above. Defining all operators as functions just makes things more consistent. |
42 | 42 | 3. If you were to create an operator that is composed of other operators you can safely do so without thinking about the order of definition in the *operators* file. The reason being that the operator is lazily created |
43 | 43 |
|
44 | 44 | ```marksy |
@@ -71,4 +71,4 @@ h(Example, { name: "guide/goingfunctional/map" }) |
71 | 71 |
|
72 | 72 | ```marksy |
73 | 73 | h(TypescriptNotice, null, "Notice here that we are typing both the input and the output. Both for the **map** operator and the **pipe** operator. This is important to manage the composition of operators. Typically operators pass on the same value they receive, meaning that you do not need the second typing parameter for the **Operator** type.") |
74 | | -``` |
| 74 | +``` |
0 commit comments