Composition

A Superpower explained

"a whole mess of useful functional programming helpers"

Composition
 

mechanism to combine simple functions to build more complicated ones

 

const users = [
  { name: "Max", joined: 2007 },
  { name: "Patrick", joined: 2001 },
  { name: "Ali", joined: 2009 },
  { name: "Ben", joined: 2002 }
];

The goal is to have a function that

- sorts the list by the users joined date and

-only returns the user’s names.

const namesSortedByJoined = (users) => {
  const sortedUsers = _.sortBy(users, 'joined');
  return _.map(sortedUsers, (user) => user.name);
}
const namesSortedByJoined = compose(
  map((user) => user.name),
  sortBy('joined'),
)
_.map(users, (user => user.name))


_.map((user => user.name), users)

Flipping the arguments

compose(funcC, funcB, funcA) == pipe(funcC, funcB, funcA)
const UserForm = ({ name, setName, age, setAge }) => (
  <form>
    <input
      type="text"
      value={name}
      onChange={(event) => setName(event.target.value)}
    />
    <input
      type="number"
      value={age}
      onChange={(event) => setAge(event.target.value)}
    />
  </form>
)

const enhanceWithName = withState('name', 'setName', null)
const enhanceWithAge = withState('age', 'setAge', null)
const enhance = compose(enhanceWithName, enhanceWithAge)

export default enhance(UserForm)
const User = ({ data }) => (
  <div>{data.user && data.user.name}</div>
)

const UserQuery = gql`
  query Query() {
    user(userId: $userId) {
      name
    }
  }
`

const enhance = compose(
  withRouter,
  graphql(UserQuery, {
    options: props => ({
      variables: {
        userId: props.params.userId,
      },
    }),
  }),
)
export default enhance(User)

How to make your APIs composable?

const pastelize = compose(
  tint(0.3),
  lighten(0.3),
  saturate(0.2)
);

const pastelRed = pastelize('red');
const pastelMagenta = pastelize('magenta');

Composition:

By nikgraf

Composition:

  • 886