# Point Free

*Fixed-point* functions are where you take one of the function's inputs and fix it at a certain value. As a result, if you were to graph that input along an axis, it would always be fixed in one position. Kind of like this:

```js
function multiply(x, y) {
  x = 3;
  return x * y;
}
```

In contrast, **point-free** functions are functions where you don't need to define its *points*, i.e., inputs.

## Point-free via equational reasoning

Imagine a function that takes a callback, where that callback calls another function:

```js
getPerson(function onPerson(person) {
  return renderPerson(person);
});
```

Notice that `onPerson` and `renderPerson` always accept the same inputs and return the same outputs. They have the *same shape*.

As a result, they are **interchangeable**, so we can replace `onPerson` with `renderPerson` directly. (**Note**: If you've reasoned like this, it's called **equational reasoning**.)

```js
getPerson(renderPerson);
```

**Important**: The key takeaway is that `renderPerson` is *point-free*. You don't have to explicitly include the `person` point.

## Point-free refactor

Take the following function relationship:

```js
function isOdd(num) {
  return num % 2 === 1;
}

function isEven(num) {
  return !isOdd(num);
}
```

This is pretty good code; it shows the negation relationship between `isOdd` and `isEven`.

But by using an *adapter function*, we can refactor `isEven` to be *point-free*.

```js
// This adapter function is formally called a "complement"
function not(fn) {
  return function negated(...args) {
    return !fn(...args);
  };
}

function isOdd(num) {
  return num % 2 === 1;
}

// Generates the complement of isOdd
const isEven = not(isOdd);
```

### Value of the refactor

In the original implementation, `isEven` had unnecessary *imperative* details. Specifically, we didn't need to know that `num` was accepted as a parameter and passed to `isOdd` as an argument.

By using a `not` adapter function and removing the need for the `num` point, we free up the reader to see the negation relationship between `isOdd` and `isEven` *even more clearly*.

We are effectively moving towards a more *declarative* style.

**Note**: Often times, declarative programming is clearer by being *more implicit*. Declarative code says a lot without needing to literally say it.

## Advanced Point-free Techniques

We can refactor `isOdd` to be point-free as well! We just need adapter functions for *modulus* and *strict equality*.

```js
function mod(y) {
  return function forX(x) {
    return x % y;
  };
}

function eq(y) {
  return function forX(x) {
    return x === y;
  };
}

const mod2 = mod(2);
const eq1 = eq(1);

function isOdd(num) {
  return eq1(mod2(num));
}
```

(**Note**: Notice how in our currying functions, `mod` and `eq`, we pass y first. This is on purpose. Generally, our code is more *ergonomic* and *usable* when we pass y first.)

Now `isOdd` is defined in terms of `mod` and `eq`, where the return value of `mod2` becomes the argument for `eq1`. This pattern is known as **composition**.

We can therefore refactor once more to use a `compose` adapter function.

```js
function compose(fn2, fn1) {
  return function composed(x) {
    return fn2(fn1(x));
  };
}

const isOdd = compose(eq(1), mod(2));
```

**Note**: Using equational reasoning, we swap `eq1` with `eq(1)` and `mod2` with `mod(2)`.


---

# 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://notes.danfitz.com/javascript/functional-light-javascript/d-point-free.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.
