我是ramda.js的新手,我编写了以下代码,该代码检查值是否尚未以提供的列表中的后缀结尾,它添加了“ px”后缀
function addSuffix(value, suffix = 'px', test = ['px', 'pt', '%']) {
return compose(
concat(value),
ifElse(anyPass(map(endsWith, test)), () => '', () => suffix)
)(value);
}
答案 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'
请注意,您可以使用addSuffix
以pointfree样式重写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>