點燈坊

學而時習之,不亦悅乎

使用 tap() Debug Ramda

Sam Xiao's Avatar 2019-08-09

初學者學習 FP 或 Ramda,會發現在 Imperative 下 Break Point 大法失效了,因為在 Pipeline 或 Compose 下,根本無從下 Break Point,此時該如何 Debug 呢 ?

Version

macOS Mojave 10.14.5
VS Code 1.36.1
Quokka 1.0.240
Ramda 0.26.1

Ramda

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

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

let usrFn = pipe(
  filter(x => x.price > 100),
  map(x => x.price),
  reduce((a, x) => a + x, 0)
);

usrFn(data); // ?

一個經典的 Ramda,將 FP 最具代表性的 filter()map()reduce() 全用上了。

debug000

Point-free

import { filter, map, pipe, reduce, add, prop, compose, lt } from 'ramda';

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

let usrFn = pipe(
  filter(compose(lt(100), prop('price'))),
  map(prop('price')),
  reduce(add, 0)
);

usrFn(data); // ?

也可進一步寫成 Point-free 版本。

debug001

Debug

import { filter, map, pipe, reduce, add, prop, compose, lt, tap } from 'ramda';

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

let usrFn = pipe(
  filter(compose(lt(100), prop('price'))),
  tap(console.log),
  map(prop('price')),
  tap(console.log),
  reduce(add, 0)
);

usrFn(data); // ?

Ramda 並不能保證沒 bug,當想要 debug 時,才發現 pipe() 根本是一行,也沒有變數,因此根本無處下 break point。

很多人就因為 FP 很難 debug 而放棄了。

filter(compose(lt(100), prop('price'))),
tap(console.log),

事實上要 debug 很簡單,只要將 console.log 傳入 tap(),就能顯示目前 pipeline 的結果,可以很清楚得知 data 到底是錯在哪一步。

debug002

Conclusion

  • tap() 並不會影響 pipeline 結果,所以可以安心用來 debug
  • Debug FP 並不需要高級工具,只要 tap() 即可

Reference

Ramda, tap()