LoginSignup
1
1

More than 5 years have passed since last update.

使って学ぶ transduce

Last updated at Posted at 2018-07-26

ramda 使って transduce のお勉強

  • まずは 出力用の reducer の定義。ふつうに (acc, x) => acc.concat([x]) としてもいいんだけど、せっかくだから transformer で実装する:
const R = require('ramda');

const xfList = {
  '@@transducer/step': (acc, x) => acc.concat([x]),
  '@@transducer/init': () => [], // ignored on transduce
  '@@transducer/result': x => x,
};
  • 2を足して 3を掛けるという map を transduce で書いてみる。mapper を関数合成するのが普通:
// reference point
const add2 = x => x + 2;
const mul3 = x => x * 3;
const f1 = x => mul3(add2(x));
[1, 2, 3].map(f1); // ->  [ 9, 12, 15 ]
R.transduce(R.map(f1), xfList, [], [1, 2, 3]); // -> [ 9, 12, 15 ]
  • mapper を compose しても良いし、 transducer を compose してもよい。compose の順序が異なるのは何度注意してもしきれない:
// composed mapper
const f2 = R.compose(mul3, add2);
R.transduce(R.map(f2), xfList, [], [1, 2, 3]); // -> [ 9, 12, 15 ]

// composed transducer. NOTE THE ORDER TO COMPOSE!
const xform = R.compose(R.map(add2), R.map(mul3));
R.transduce(xform, xfList, [], [1, 2, 3]); // -> [ 9, 12, 15 ]
  • とはいえ、mapper を compose する方向は、filter が出てくると詰むので、transducer を compose するのがいいだろう:
// composed transducer. compotition of map and filter
const xform2 = R.compose(xform, R.filter(x => x % 2));
R.transduce(xform2, xfList, [], [1, 2, 3]); // -> [ 9, 15 ]
  • transformer の形でロジックを書いておく利点は、input や output が変わってもロジック部である transformer の実装をいじる必要がないということ:
// pluggable input
const g = (function* mygen() { yield 1; yield 2; yield 3; }());
R.transduce(xform, xfList, [], g); // -> [ 9, 12, 15 ]

// pluggable output
const xfString = {
  '@@transducer/step': (acc, x) => `${acc},${x}`,
  '@@transducer/init': () => 'X', // ignored on transduce
  '@@transducer/result': x => x,
};
R.transduce(xform, xfString, '', [1, 2, 3]); // -> ',9,12,15'
  • 普段は transduce よりも into を使う方が見た目がわかりやすい:
// in most cases, use into in favor of transduce
R.into([], xform, [1, 2, 3]); // -> [ 9, 12, 15 ]
R.into('', xform, [1, 2, 3]); // -> '91215'
R.into(xfList, xform, [1, 2, 3]); // -> [ 9, 12, 15 ]
R.into(xfString, xform, [1, 2, 3]); // -> 'X,9,12,15'

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1