# 如何使用 chain() 取代 filter() + map() ?

`filter()``map()` 都是 FP 代表性的 Higher Order Function，但也可使用 `chain()` 實踐。

VS Code 1.33.0

Quokka 1.0.209

Ramda 0.26.1

## map()

```import { map } from 'ramda';

let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
];

let getBooks = map(x => {
if (x.price < 300)
return `\${x.title} is not expensive`;
});

console.dir(getBooks(data));
```

## filter() + map()

```import { pipe, map, filter } from 'ramda';

let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
];

let getBooks = pipe(
filter(x => x.price < 300),
map(x => `\${x.title} is not expensive`)
);

console.dir(getBooks(data));
```

## Point-free

```import { pipe, map, filter, prop, gt, concat, __ } from 'ramda';

let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
];

let getBooks = pipe(
filter(pipe(prop('price'), gt(300))),
map(pipe(prop('title'), concat(__, ' is not expensive')))
);

console.dir(getBooks(data));
```

Point-free 的目的就是讓可讀性變高，但有時條件太複雜，反而會使 callback 更複雜，因此要視情況使用

## chain()

```import { chain } from 'ramda';

let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
];

let getBooks = chain(x => {
if (x.price < 300)
return [`\${x.title} is not expensive`];
else
return [];
}
);

console.dir(getBooks(data));
```

`map()` 改成 `chain()` ，且維持原本 callback 大架構不變。

`return string` 改成 `return array of string`

## Conclusion

• `chain()` 會維持原本 `map()` callback 的大架構，只要稍微重構即可
• `filter()` + `map()` 改寫幅度較大，觀念也不太一樣
• `filter()` + `map()` 似乎不太需要 Point-free，因為可讀性並沒有變高
• `chain()` 的寫法是否有比 `filter()` + `map()` 好比較見仁見智，但也不失為漂亮的寫法