我刚刚进入函数式编程,我很难搞清楚如何做到这一点(如果它甚至值得麻烦)。我已经考虑过curry,我不确定这是否是我需要去的方向?还是管道?
我想从一个值开始,然后通过不同的函数进行管道。 Underscore具有类似的“链”方法。但是我不想使用原型来做到这一点。我意识到解决方案可能与我的目标语法不匹配。
Elm具有|>
语法(如下所示),这非常适合查看
// what i'd like to do (or similar) in JS *without using prototype*
num = ("(123) 456-7890")
.removeDashes()
.removeParens()
.removeSpaces()
// what elm does
"(123) 456-7890"
|> removeDashes
|> removeParens
|> rem
// functions I wrote so far
removeDashes = function(str) {
return str.replace(/-/g, '');
};
removeParens = function(str) {
return str.replace(/\(|\)/g, '');
};
removeSpaces = function(str) {
return str.replace(/\s/g, '');
};
// what i'm currently doing
num =
removeDashes(
removeParens(
removeSpaces(
"(123) 456-7890"")));
答案 0 :(得分:3)
有不同的方法来解决这个问题,你提供了下划线和榆树的参考。
在Elm中,curried函数是等式的重要组成部分。由于每个函数都接收一个参数,您可以构建链,其中一些部分应用,等待您使用管道编织的参数。这同样适用于Haskell,PureScript及其同类语言。
在JavaScript中重现 ipsis literis 需要一点点糖 - 你可以使用sweet.js macro来获得执行它的源转换。
没有糖,它可以有很多方面。也许探索的一种方法是使用生成器,将已解析链的位向下传递,直到获得非函数值。
答案 1 :(得分:3)
如果您希望通过JavaScript中的函数式编程让您感觉不舒服,我建议您使用像Underscore,Lodash或Ramda这样的库。所有都具有撰写/管道功能。大多数时候,您希望将其与某些图书馆也提供的某种形式的部分应用程序相结合。
无论如何,尝试自己实施它是一个很好的练习。 我会像这样解决它......
/* Asumes es5 or higher */
function pipe (firstFn /* ...restFns */) {
var _ = null;
var _slice = Array.prototype.slice;
var restFns = _slice.call(arguments, 1) || [];
return function exec_fns() {
var args = _slice.call(arguments, 0, 1);
return restFns.reduce(function(acc, fn) {
return fn.call(_, acc);
}, firstFn.apply(_, args));
}
}
removeDashes = function(str) {
return str.replace(/-/g, '');
};
removeParens = function(str) {
return str.replace(/\(|\)/g, '');
};
removeSpaces = function(str) {
return str.replace(/\s/g, '');
};
console.log(pipe(
removeDashes,
removeParens,
removeSpaces
)("(123) 456-7890") == "1234567890")
Fogus的功能JavaScript也是深入挖掘这种编程风格的好资源
答案 2 :(得分:2)
就像最后说的那样,看看使用原型。字符串原型允许您向所有字符串添加类级功能:
String.prototype.removeParens = function() {
this = this.replace(/\(|\)/g, '');
}
这可以让你做到这样的事情:
var myString = "(test)";
myString.removeParens();
一旦将其他函数添加到String原型中,您就可以简单地链接函数调用,如下所示:
myString.removeDashes().removeParens().removeSpaces();
等
答案 3 :(得分:1)
这是我在lodash中找到的解决方案,它允许您混合自己的功能,然后将它们用于链:
accountList
答案 4 :(得分:1)
不是一个非常严肃的建议,但一个可行的建议:
def flash(self,count):
bg = self.crhw.cget('background')
fg = self.crhw.cget('foreground')
self.crhw.configure(background=fg,foreground=bg)
count +=1
if (count < 31):
print count, bg, fg
self.crhw.after(1000,self.flash(count))
#And I call it with something like
self.flash(0) #to initialize the count
这是基于var update = pipe()(removeDashes >> removeParens >> removeSpaces);
update("(123) 456-7890"); //=> "1234567890"
的实现:
pipe
您可以在我slide 33的演讲的functional composition in js中查看更多内容。
答案 5 :(得分:1)
您可以在一行中创建管道功能,具有良好的可读性:
const pipe = (...fns) => fns.reduce((v, f) => v.constructor === Function ? v() : f(v));
它将以这种方式使用:
var numResult = pipe('(123) 456-7890', removeDashes, removeParens, removeSpaces);
var pipe = (...fns) => fns.reduce((v, f) => v.constructor === Function ? v() : f(v));
function removeDashes(str) {
return str.replace(/-/g, '');
}
function removeParens(str) {
return str.replace(/\(|\)/g, '');
}
function removeSpaces(str) {
return str.replace(/\s/g, '');
}
console.log(
'result:', pipe('(123) 456-7890', removeDashes, removeParens, removeSpaces)
);
&#13;
注意:此功能需要一个支持传播运营商...
的平台。
为了以防万一,我已经为此创建了一个支持异步功能(Promises)的模块,它也适用于无法使用传播...
的旧/旧版平台