Sebastian Herrmann
A software-developing peep.
Software Developer at
import * as _ from 'lodash';
const activeUsernames = _(users)
.filter({ isActive: true })
.map('username')
.sort()
.value();
const isMature = age => age > 17;
const getAge = user => user.profile.age;
const getAge = get('profile.age');
import { compose, map, filter } from 'lodash/fp';
const getName = user => user.name;
const isDeveloper = user => user.job === 'dev';
const getDevNames = compose(
map(getName), filter(isDeveloper)
);
const devNames = getDevNames(users);
// Curried function to multiply two integers.
Function<Integer, Function<Integer, Integer>> multiply =
new Function<Integer, Function<Integer, Integer>>() {
@Override
public Function<Integer, Integer> apply(Integer a) {
return new Function<Integer, Integer>() {
@Override
public Integer apply(Integer b) {
return a * b;
}
};
}
};
// Multiply two integers.
const multiply = a => b => a * b;
// ❌ mutability
const user = { name: 'Sandra' };
user.name = 'Fred';
// ✅ immutability
const user = { name: 'Sandra' };
const changedUser = { ...user, name: 'Fred' };
// ❌ impure function
const getStateImpure = () => window.appState.name;
// ✅ pure function
const getState = currentWin => currentWin.appState.name;
// ✅ via lodash/fp
const getState = get('appState.name');
partial application
import * as _ from 'lodash';
const devNamesChained = _(users)
.filter(isDeveloper)
.map(getName)
.value();
import { compose, map, filter } from 'lodash/fp';
const getDevNames = compose(
map(getName),
filter(isDeveloper),
);
getDevNames(users);
const getDevNamesUpper = compose(
toUpper,
getDevNames,
);
map(multiply(2), [1, 2, 3, 4]);
// => [2, 4, 6, 8]
withData({users: api.loadUsers}, UserListPage);
// => UserListPage called with prop "users"
const getCommentsWritten = get('commentsWritten');
const isUserActive = get('isActive');
// [User] -> Number
const getTotalNrCommentsWritten = compose(
sum,
map(getCommentsWritten)
);
// [User] -> Number
const getAverageCommentsWritten = compose(
mean,
map(getCommentsWritten)
);
// [User] -> Number
const getAverageCommentsWrittenActiveUsers = compose(
getAverageCommentsWritten,
filter(isUserActive)
);
const getManagers =
users => users.filter(user => user.isManager);
const getNamesOfManagers =
users => getManagers(users).map(user => user.name);
// VS
const getManagers = filter(get('isManager'));
const getNamesOfManagers = compose(map(get('name')), getManagers);
// pointfree functions
import { compose } from 'lodash/fp';
import { mapProps, withState } from 'recompose';
import { withAppContext } from '../../hoc/withAppContext';
// "Plain" stateless component
const ReadMoreText = (/*...*/) => {/*...*/};
// Component with state and context
export default compose(
withAppContext,
withState('expanded', 'setExpanded', false),
mapProps(sanitizeText),
)(ReadMoreText);
Open your editor, Sebastian.
Use FP as much as you like!
(But don't throw consistency overboard.)
Questions? Comments? Opinions?
Slides: bit.ly/fp-slides
By Sebastian Herrmann
We highlight how we're using FP in the frontend in combination with JavaScript and React to build readable and reusable functions and components.