# Functional Programming
> Concept & Example
---
### Pure functions
### Function Composition
### Avoid shared/mutating state
### Avoid side effects
---
## Pure Function
> ƒ(x) = x
----
![](https://i.imgur.com/FkUpkZm.png =x400)
----
![](https://i.imgur.com/8S7lE2l.png)
```javascript=
const toFahrenheit = celcius =>
celcius * 9/5 + 32
```
---
## Function Composition
> ƒ( g(x) )
----
![](https://i.imgur.com/rPa2Xfc.png =x500)
----
### Composition
```javascript=
const f = x => Math.pow(x, 2)
const g = x => x + 1
const gComposeF = R.compose(g, f)
gComposeF(3) // 10
```
----
### Pipe
```javascript=
const f = x => Math.pow(x, 2)
const g = x => x + 1
const fThenG = R.pipe(f, g)
fThenG(3) // 10
```
---
## Avoid shared/mutating state
> Subtle bug
```javascript=
const list = [1,2,3,3,4,5];
for (var i = 0; i < list.length; ++i) {
if (list[i] === 3) {
list.splice(i, 1);
}
}
console.log(list); // [1,2,3,4,5]
```
----
```javascript=
const list = [1,2,3,3,4,5];
console.log(
list.filter(item => item !== 3)
); // [1,2,4,5]
console.log(list); //[1,2,3,3,4,5]
```
---
## Avoid side effect
- Generally, avoid IO operation in functions.
- In JavaScript: Decompose complex functions into pure functions.
- Application without side effect is probably useless.
---
### Different Ways on FP (and managing side effect)
- FP design patterns
- Algebraic structures like Monads/Monoids/Functor/others
- Pattern Matching
- Reactive functional programming
---
### Algebraic Data Structure
- Details:
- JS ???
- FP languages: OCaml/Elixir/Scala/Elm/PureScript
----
### "Common" Algebraic Data Types
![](https://i.imgur.com/nEd1sTr.png)
[Functor](https://github.com/fantasyland/fantasy-land#functor) • [Applicative](https://github.com/fantasyland/fantasy-land#applicative) • [Monad](https://github.com/fantasyland/fantasy-land#monad)
---
### Cut to the chase...
Example use case:
- Calculate the temperature reading in Farenheit from a single thermometer probe, after 20ºC temperature increment.
- Similar to above, but for a grouped reading from thermometers from different locations, by taking the average reading.
----
```scala=
def convertCelciusToFarenheit(celcius: Double) =
celcius * 9/5 + 32
def increaseTemp(increment: Double, initial: Double) =
initial + increment
def increaseTempBy20 =
increaseTemp(20, _: Double)
def sum(numbers: Seq[Double]) =
numbers.reduce(_ + _)
def mean(numbers: Seq[Double]) =
sum(numbers) / numbers.length
```
----
```scala=
Option(potentiallyNullTemperature)
.map(increaseTemperatureBy20)
.map(convertCelciusToFarenheit)
// => Some(number)
// => None (if `potentiallyNullTemperature` is null)
val probesTemperatureInCelcius = Map(
"location1" -> List(23.3, 45.2, 23.4),
"location2" -> List(24.9)
)
probesTemperatureInCelcius.values.flatten
.map(increaseTemperatureBy20)
.map(convertCelciusToFarenheit)
// => List(23.3, 45.2, 23.4, 24.9)
```
----
### Algebraic Operation Ecosystem In JavaScript
- [fantasy-land](https://github.com/fantasyland/fantasy-land) specs ❓
- [ramda](https://ramdajs.com/) 👍🏼
----
#### Functional Programming in JS
Modified example from https://fr.umio.us/favoring-curry/ (plain JS):
```javascript=
const getIncompleteTaskSummaries = function(membername) {
return fetchData()
.then(({tasks}) => tasks)
.then(tasks => tasks.filter(
({username}) => membername)
)
.then(tasks => tasks.filter(
({complete}) => !complete)
)
.then(tasks => tasks.map(
({id, dueDate, title, priority}) =>
({id, dueDate, title, priority})
))
.then(abbreviatedTasks =>
abbreviatedTasks.sort(({dueDate}) => dueDate)
);
};
```
----
For readability and testability:
```javascript=
const extractUsername = (membername) => tasks =>
tasks.filter(({username}) => membername)
const notComplete = tasks =>
tasks.filter(({complete}) => !complete)
const extractImportantAttributes = tasks =>
tasks.map(
({id, dueDate, title, priority}) =>
({id, dueDate, title, priority})
)
const sortByDueDate = abbreviatedTasks =>
abbreviatedTasks.sort(({dueDate}) => dueDate)
const getIncompleteTaskSummaries = function(membername) {
return fetchData()
.then(({tasks}) => tasks)
.then(extractUsername(membername))
.then(notComplete)
.then(extractImportantAttributes)
.then(sortByDueDate)
};
```
----
Ramda equivalent:
```javascript=
var getIncompleteTaskSummaries = function(membername) {
return fetchData()
.then(R.get('tasks'))
.then(R.filter(R.propEq('username', membername)))
.then(R.reject(R.propEq('complete', true)))
.then(R.map(R.pick(
['id', 'dueDate', 'title', 'priority']
)))
.then(R.sortBy(R.get('dueDate')));
};
```
----
#### Scala
```scala=
case class Task( ... )
case class Response(task: Task)
val fetchData: Future[Response] = Future { ... }
fetchData
.map(_.task)
.filter(_.username == membername)
.filterNot(_.complete == true)
.map(TaskDto(
id = _.id,
dueDate = _.dueDate,
title = _.title,
priority = _.priority
))
.sortBy(_.dueDate)
```
> FP-style: Work with the "box" safely.
---
## Pattern Matching
```scala=
case class TaskDto(id: Long, dueDate: Date, title: String, priority: Priority)
val aTaskDto: Option[TaskDto] = _
aTaskDto match {
case Some(TaskDto(_, _, _, priority)) if priotity == Priority.High =>
escalatedProcessing()
case Some(TaskDto(_, dueDate, _, _)) if dueDate.after(DueDate) =>
prioritisedProcessing()
case Some(TaskDto) =>
normalTaskProcessing()
case _ =>
doNothing()
}
```
----
#### Reusability and testability
```scala=
val wayToProcessTheTask = {
case Some(TaskDto(_, _, _, priority)) if priotity == Priority.High =>
escalatedProcessing()
case Some(TaskDto(_, dueDate, _, _)) if dueDate.after(DueDate) =>
prioritisedProcessing()
case Some(TaskDto) =>
normalTaskProcessing()
case _ =>
doNothing()
} // this is a partial function
val taskDtos: List[TaskDto] = _
taskDtos.map(wayToProcessTheTask)
```
---
## Reactive functional programming
![](https://i.imgur.com/UKuS3JJ.png)
----
Examples:
- [ReactiveX](http://reactivex.io/): Async programming with observable stream
- RxJS, RxScala, RxJava
- Spring 5 no longer MVC, but reactive using Java stream.
- In data processing categories: akka-stream / Apache Spark streams / Apache Flink
- On the UI: https://cycle.js.org/
----
Why "reactive **functional** programming"?
> Discussion
>
---
Q&As
{"metaMigratedAt":"2023-06-14T18:37:40.323Z","metaMigratedFrom":"Content","title":"Functional Programming","breaks":true,"contributors":"[{\"id\":\"b0d38937-48da-4a45-8f43-2ae9039a2c07\",\"add\":9281,\"del\":2478}]"}