如何改善我编写的ramda代码?

时间:2019-07-12 10:03:37

标签: ramda.js

我是ramda.js的新手,我编写了以下代码,该代码检查值是否尚未以提供的列表中的后缀结尾,它添加了“ px”后缀


function addSuffix(value, suffix = 'px', test = ['px', 'pt', '%']) {
  return compose(
    concat(value),
    ifElse(anyPass(map(endsWith, test)), () => '', () => suffix)
  )(value);
}

2 个答案:

答案 0 :(得分:2)

也许我的第一个建议是避免使用默认参数。它们通常不能很好地使用咖喱函数。

您可以编写返回函数的函数,以检查字符串是否以给定的后缀列表结尾:

const hasSuffixFn = compose(anyPass, map(endsWith));
const hasSuffix = hasSuffixFn(['px', 'pt', '%']);

hasSuffix('foo'); // false
hasSuffix('1px'); // true

然后,您可以使用一个函数,该函数带有一个后缀列表和一个后缀,并返回一个函数,该函数将在后缀不存在时附加该后缀:

const addSuffix = (suffixes, suffix) => unless(hasSuffix(suffixes), flip(concat)(suffix));

const addPx = addSuffix(['px', 'pt', '%'], 'px');
addPx('10'); // '10px'
addPx('10px'); // '10px'
addPx('10pt'); // '10pt'

请注意,您可以使用addSuffixpointfree样式重写useWith

const addSuffix = useWith(unless, [hasSuffix, flip(concat)]);

完全放入

const hasSuffix = compose(anyPass, map(endsWith));
const addSuffix = (suffixes, suffix) => unless(hasSuffix(suffixes), flip(concat)(suffix));
const addPx = addSuffix(['px', 'pt', '%'], 'px');

console.log(addPx('10'));
console.log(addPx('10px'));
console.log(addPx('10pt'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {anyPass, endsWith, unless, flip, concat, compose, map} = R;</script>


APPENDIX

为什么不使用默认参数?

我不知道在函数式编程中是否建议使用默认参数,但是我已经意识到,当您需要部分应用函数时,它们通常会妨碍您的使用。

看看这个:

这里我们有一个将三个数字相加的函数:

const foo = (a, b, c) => a + b + c;
foo(10, 20, 30); // 60

我们可以对此进行处理,并开始部分应用该功能:

const foo_curried = curry(foo);
foo_curried(10, 20, 30); // 60
foo_curried(10, 20)(30); // 60
foo_curried(10)(20, 30); // 60
foo_curried(10)(20)(30); // 60

让我们写一个类似的函数,但是带有默认参数。可以按预期工作:

const bar = (a=10, b=20, c=30) => a + b + c;
bar();              // 60
bar(110);           // 160
bar(110, 220);      // 360
bar(110, 220, 330); // 660

但是,如果您想咖喱并部分应用它,则会出现错误:

const bar_curried = curry(bar);
bar_curried();              // 60
bar_curried(110);           // 160
bar_curried(110)(220, 330); // Error!

为什么?咖喱函数一直等到您提供了所有参数。在此之前,它将一直返回接受剩余参数的函数。但是,如果您部分应用具有默认参数的函数,那么您将无法真正预测咖喱函数将返回什么:最终结果还是接受剩余参数的函数?

在最后一个示例中,bar_curried(110)直接返回结果,即110 + 20 + 30,并且当您尝试像调用函数一样调用数字时会出现错误。

答案 1 :(得分:0)

您还可以避免传递后缀列表,因为它看起来是多余的...只需确保给定的value不以数字结尾:

const ensureSuffix = R.curry((suffix, value) =>
  R.unless(R.test(/\D$/), v => `${v}${suffix}`, value),
);

const addPx = ensureSuffix('px');

console.log(addPx(15));
console.log(addPx('15pt'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>