我怎样才能像JS那样管理JS中的函数呢?

时间:2015-09-09 16:59:29

标签: javascript underscore.js elm

我刚刚进入函数式编程,我很难搞清楚如何做到这一点(如果它甚至值得麻烦)。我已经考虑过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"")));

6 个答案:

答案 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);

&#13;
&#13;
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;
&#13;
&#13;

注意:此功能需要一个支持传播运营商...的平台。

为了以防万一,我已经为此创建了一个支持异步功能(Promises)的模块,它也适用于无法使用传播...的旧/旧版平台

https://github.com/DiegoZoracKy/pipe-functions