# Functional Programming

## Principles

* Separate data from behavior
* Use of declarative functions (as opposed to imperative)
* Proper use of caching (computing efficiency)
* Pure functions
* Composing (chained atomic pure operations)

## Pure functions

* Don't mutate state (global scope)
* Always have a return statement. This is useful for chaining purposes
* Idempotence. On the same input, return the same output, regardless of how many times executed
* Usually have 1 argument

```javascript
//Side effects:
const array = [1,2,3];
function mutateArray(arr) {
  arr.pop()
}
function mutateArray2(arr) {
  arr.forEach(item => arr.push(1
  ))
}
//The order of the function calls will matter.
mutateArray(array)
mutateArray2(array)
array
```

```javascript
// Idempotence:
function notGood() {
  return Math.random()
  // new Date();
}

function good() { //pure function
  return 5
}

Math.abs(Math.abs(10)) //pure function
```

## Cache in memory

```javascript
//Memoization
//learn to cache
function addTo80(n) {
  return n + 80;
}

addTo80(5)

let cache = {};
function memoizeAddTo80(n) {
  if (n in cache) {
    console.log('quickly rerieved from cache');
    return cache[n];
  } else {
    console.log('expensive operation');
    const answer = n + 80;
    cache[n] = answer;
    return answer;
  }
}
```

Here is a better implementation of caching, making the above pure.

```javascript
// let's make that better with no global scope.
function memoizeAddTo80(n) { 
  let cache = {};
  return function(n) { //This is closure in javascript.
    if (n in cache) {
      console.log('quickly rerieved from cache');
      return cache[n];
    } else {
      console.log('expensive operation');
      const answer = n + 80;
      cache[n] = answer;
      return answer;
    }
  }
}

const memoized = memoizeAddTo80();
console.log(1, memoized(6))
// console.log(cache)
// console.log('-----------')
console.log(2, memoized(6))
```

## Currying and Composing

**Currying** in JavaScript transforms a function that takes multiple arguments into a sequence of functions, each taking a single argument. For example, a function `f(a, b)` becomes `f(a)(b)`. It allows partial application of functions, where you can fix some arguments and pass others later, enabling more flexible function usage.

```javascript
// add two numbers
const add = a => b => a + b;

//similar to
const add2 = a => {
    return b => {
        return (a + b)
        }
    }

const result = add(2)(3); // => 5
```

### pipe() and compose()

Composing is the process of chaining functions. In other words, through `pipe()` and `compose()` we create a pipeline of functions with the output of one function connected to the input of the next. This is the reason for which these functions need to be pure.

{% tabs %}
{% tab title="chaining functions" %}

```javascript
//as seen on freecodecamp.org/news/pipe-and-compose-in-javascript-5b04004ac937/

//Let’s write a function that returns someone’s name.
getName = (person) => person.name;
getName({ name: 'Buckethead' });
// 'Buckethead'

//Let’s write a function that uppercases strings.
uppercase = (string) => string.toUpperCase();
uppercase('Buckethead');
// 'BUCKETHEAD'

//What if we want to add a function that gets the first 6 characters of a string?
get6Characters = (string) => string.substring(0, 6);
get6Characters('Buckethead');
// 'Bucket'

//Let’s get really crazy and add a function to reverse strings.
reverse = (string) =>
  string
    .split('')
    .reverse()
    .join('');

reverse('Buckethead');
// 'daehtekcuB'


//chaining all the operations would result in
reverse(get6Characters(uppercase(getName({ name: 'Buckethead' }))));
// 'TEKCUB
```

{% endtab %}
{% endtabs %}

Instead of jamming functions within functions or creating a bunch of intermediate variables, let’s `pipe` all the things!

```javascript
// Function composition enabling pipe functionality using reduce()
const pipe = (...functions) => input => functions.reduce(
    (acc, fn) => fn(acc),
    input
)
```

{% tabs %}
{% tab title="pipe" %}

```javascript
pipe(
  getName,
  uppercase,
  get6Characters,
  reverse
)({ name: 'Buckethead' });
// 'TEKCUB'
```

{% endtab %}
{% endtabs %}

`compose()` is similar, it just deals with the chain in the opposite direction (from right to left).

```javascript
const g = n => n + 1;
const f = n => n * 2;

const h = x => f(g(x))
h(30); //=> 62

const compose = (f, g) => x => f(g(x));
compose(f,g)(30); //=> 62
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mihai-gheorghe.gitbook.io/tic/functional-programming.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
