DEV Community

Cover image for Functional Programming: Composition of Functions
Pratik sharma
Pratik sharma

Posted on • Originally published at coolhead.in

Functional Programming: Composition of Functions

Input of one function comes from the output of another function.

👆 simple defination of function composition that i could find.

In functiona Programming, Composition takes the place of inheritance in OOP.

composition > inheritance.

it's just better to use composition from the start. It's more flexible, it's more powerful, and it's really easy to do.

Creating a Compose Function

A lot of Javascript FP libraries like ramda, provide pipe() and compose() , which help us in creating composition of functions. Before moving to those,let's create our own example functions.

Here is an example of compose function which take two functions as argument.

let compose = function(fn1, fn2) {
return fn2(fn1)
}

//or

let compose = (fn1,fn2) => fn2(fn1)
Enter fullscreen mode Exit fullscreen mode

Compose Vs Curry

Curry functions are always unary functions which take one argument per application.

Currying functions looks a lot similar pattern to composition, which often causes them to be mistaken for each other.

example of a curry function

const sum = a => b => a + b
sum(3)(5) // 8
Enter fullscreen mode Exit fullscreen mode

Are 'Currying' and 'Composition' the same concept in javascript?

No.

First, currying is translating a function that takes multiple arguments into a sequence of functions, each accepting one argument.

here, Notice the distinct way in which a curried function is applied, one argument at a time.

// not curried
const add = (x,y) => x + y;
add(2,3); // => 5

// curried
const add = x => y => x + y;
add(2)(3); // => 5
Enter fullscreen mode Exit fullscreen mode

Second, function composition is the combination of two functions into one, that when applied, returns the result of the chained functions.

const compose = f => g => x => f(g(x));

compose (x => x * 4) (x => x + 3) (2);
// (2 + 3) * 4
// => 20
Enter fullscreen mode Exit fullscreen mode

The two concepts are closely related as they play well with one another. Generic function composition works with unary functions (functions that take one argument) and curried functions also only accept one argument (per application).

Function Composition

Function composition is a way of combining pure functions to build more complicated ones. Like the usual composition of functions in mathematics, the result of one function is passed as the argument of the next, and the result of last one is the result of the whole.

Composition is a fancy term which means "combining".

In other words, we can often "combine" multiple steps either into one line of code, or into a new function to contain them

For example, if we want to find the sine of 30 degrees (remember sine uses radians) we could "compose" these two items into the single line: result = sin( degrees_to_radians( 30 ) ). This is the same as in math where we often see f(g(x)).

Example of a compose function which take more than two functions, and applies from left to right manner

We can write a function to compose as many functions as you like. In other words, compose() creates a pipeline of functions with the output of one function connected to the input of the next.

const compose = (...fns) => (x) => fns.reduceRight((y, fn) => fn(y), x);
Enter fullscreen mode Exit fullscreen mode

This version takes any number of functions and returns a function which takes the initial value, and then uses reduceRight() to iterate right-to-left over each function, f, in fns, and apply it in turn to the accumulated value, y. What we're accumulating with the accumulator, y in this function is the return value for the function returned by compose().

Now we can write our composition like this:

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

// replace `x => f(g(x))` with `compose(f, g)`

const h = compose(f, g);
h(20); //=> 42 
Enter fullscreen mode Exit fullscreen mode

Composition in React

Creating a composition for Different buttons

const Button = props => {
  return <button>{props.text}</button>
}

const SubmitButton = () => {
  return <Button text="Submit" />
}

const LoginButton = () => {
  return <Button text="Login" />
}
Enter fullscreen mode Exit fullscreen mode

Pass methods as props

A component can focus on tracking a click event, for example, and what actually happens when the click event happens is up to the container component:

const Button = props => {
  return <button onClick={props.onClickHandler}>{props.text}</button>
}

const LoginButton = props => {
  return <Button text="Login" onClickHandler={props.onClickHandler} />
}

const Container = () => {
  const onClickHandler = () => {
    alert('clicked')
  }

  return <LoginButton onClickHandler={onClickHandler} />
}
Enter fullscreen mode Exit fullscreen mode

Using children

The props.children property allows you to inject components inside other components.

The component needs to output props.children in its JSX:

const Sidebar = props => {
  return <aside>{props.children}</aside>
}
Enter fullscreen mode Exit fullscreen mode

and you embed more components into it in a transparent way:

<Sidebar>
  <Link title="First link" />
  <Link title="Second link" />
</Sidebar>
Enter fullscreen mode Exit fullscreen mode

Notice how the App component doesn't expose the structure of the data. TodoList has no idea that there is label or status properties.

The so called render prop pattern is almost the same except that we use the render prop and not children for rendering the todo.

function TodoList({ todos, children }) {
  return (
    <section className='main-section'>
      <ul className='todo-list'>{
        todos.map((todo, i) => (
          <li key={ i }>{ children(todo) }</li>
        ))
      }</ul>
    </section>
  );
}

function App() {
  const todos = [
    { label: 'Write tests', status: 'done' },
    { label: 'Sent report', status: 'progress' },
    { label: 'Answer emails', status: 'done' }
  ];
  const isCompleted = todo => todo.status === 'done';
  return (
    <TodoList todos={ todos }>
      {
        todo => isCompleted(todo) ?
          <b>{ todo.label }</b> :
          todo.label
      }
    </TodoList>
  );
}
Enter fullscreen mode Exit fullscreen mode

Discussion (5)

Collapse
pengeszikra profile image
Peter Vivo

Why we don't use proposal pipeline operator? Which is give composition without any library or helper function, and very useful in multiple case.

42 |> f |> g;
Enter fullscreen mode Exit fullscreen mode

Pipeline operator handy even simple log:

data |> functionForTest |> console.log;
Enter fullscreen mode Exit fullscreen mode

in react also handy this syntax sugar.

  const getTextAreaValue = ({target:{value}}) => value;
  <TextArea onChange={event => event |> getTextAreaValue |> myAction}</TextArea>
Enter fullscreen mode Exit fullscreen mode

or better

  const inputFromTextArea = action => ({target:{value}}) => value |> action;
  <TextArea onChange={myAction |> inputFromTextArea}</TextArea>
Enter fullscreen mode Exit fullscreen mode
Collapse
vonheikemen profile image
Heiker

I think there are two proposals for the pipeline operator. There is one where the operator behaves exactly like pipe() and the other proposal adds more features to it (they call it smart pipeline).

I like the idea of the simple pipeline but I imagine that a large part of the javascript community would not like such a limited feature. It would force them to learn about partial application, unary functions, and currying; in other words it would impose a specific style of programming on them. If it doesn't make their life easier they would just ignore it.

Collapse
pratiksharm profile image
Pratik sharma Author

Thanks to both of you! I was not aware of this new experimental pipeline operator. I like the syntax that peter has used. as per the current mozilla docs it is still in stage 1, so i don't think we can use the operator just for now. Operators have made our life easier a bit, so much time i use ? : , then using if else. I think we are moving to more simplified and less bracket world of programming.

Thread Thread
pengeszikra profile image
Peter Vivo

If you would try pipeline operator, then you found in this parcel bunlder setup: github.com/Pengeszikra/react-base , react can easy remove from this.
Eslint give correct result. But one more trick for VS-Code don't show error in

"javascript.validate.enable": false,
Enter fullscreen mode Exit fullscreen mode
Thread Thread
pratiksharm profile image
Pratik sharma Author

Sure will give it a try!