Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/453.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何像Elm那样在JS中使用管道函数?_Javascript_Underscore.js_Elm - Fatal编程技术网

Javascript 如何像Elm那样在JS中使用管道函数?

Javascript 如何像Elm那样在JS中使用管道函数?,javascript,underscore.js,elm,Javascript,Underscore.js,Elm,我刚刚开始学习函数式编程,我很难弄明白如何做到这一点(如果这是值得的话)。我研究过咖喱,不确定这是否是我需要走的方向??还是管道 我想从一个值开始,然后通过不同的函数传递它。下划线具有类似的“chain”方法。然而,我不想使用原型来实现这一点。我意识到解决方案可能与我的目标语法不匹配 Elm的|>语法(如下)非常好看 // what i'd like to do (or similar) in JS *without using prototype* num = ("(123) 456-7890

我刚刚开始学习函数式编程,我很难弄明白如何做到这一点(如果这是值得的话)。我研究过咖喱,不确定这是否是我需要走的方向??还是管道

我想从一个值开始,然后通过不同的函数传递它。下划线具有类似的“chain”方法。然而,我不想使用原型来实现这一点。我意识到解决方案可能与我的目标语法不匹配

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"")));

正如hindmost所说,研究使用原型。字符串原型允许您向所有字符串添加类级功能:

String.prototype.removeParens = function() {
    this = this.replace(/\(|\)/g, '');
}
这使您可以执行以下操作:

var myString = "(test)";

myString.removeParens();
myString.removeDashes().removeParens().removeSpaces();
一旦您将其他函数添加到字符串原型中,您就可以像这样简单地链接函数调用:

var myString = "(test)";

myString.removeParens();
myString.removeDashes().removeParens().removeSpaces();

等等。

最简单的方法就是将它们添加到原型链中,但是你可以用一个对象来完成。下面是一个简单的例子:

function MyString( str ){
    var value = str.toString();

    return {
        removeDashes: function() {
            value = value.replace(/-/g, '');
            return this;
        },
        removeParens: function() {
            value = value.replace(/\(|\)/g, '');
            return this;
        },
        removeSpaces: function() {
            value = value.replace(/\s/g, '');
            return this;
        },
        toString: function (){
            return value;
        },
        valueOf: function (){
            return value;
        }
    };
}
稍后您可以执行以下操作:

var clean = (new MyString('This \\(Is)\/ Dirty'))
    .removeDashes()
    .removeParens()
    .removeSpaces();

这样,您将保持
原型的清洁。要检索非对象值,只需运行
toStrong()
方法,
toValue()
或对该值执行任何操作(contatenating 1,divide it,anything!)。

正如其他人所说,将函数添加到字符串原型中是一个有效且简短的解决方案。但是,如果您不想将它们添加到字符串原型中,或者如果您想在将来执行更复杂的函数,另一种选择是制作一个包装器来处理此问题:

function SpecialString(str){

    this.str = str;

    this.removeDashes = function() {
      this.str=this.str.replace(/-/g, '');
      return this;
    };

    this.removeParens = function() {
      this.str=this.str.replace(/\(|\)/g, '');
      return this;
    };

    this.removeSpaces = function() {
      this.str=this.str.replace(/\s/g, '');
      return this;
    };

    return this;
}

num = new SpecialString("(123) 456-7890").removeDashes().removeParens().removeSpaces();

console.log(num) // 1234567890

下面是我在lodash中找到的一个解决方案,它允许您混合自己的函数,然后使用它们来对抗链:

...

removeSpaces = function(str) {
  return str.replace(/\s/g, '');
};

_.mixin({
  removeSpaces: removeSpaces,
  removeParens: removeParens,
  removeDashes: removeDashes
});

num = _.chain("(123) 456-7890")
  .removeSpaces()
  .removeParens()
  .removeDashes()
  .value()

有不同的方法来解决这个问题,您在下划线和Elm中提供了参考

在Elm中,curried函数是方程的重要组成部分。由于每个函数都接收一个参数,因此可以构建部分应用这些参数的链,等待管道中编织的参数。这同样适用于Haskell、PureScript及其同类语言

在JavaScript中复制ipsis literis需要一点糖分——您可以使用a来获得实现这一点的源代码转换


没有糖,它可以走很多路。也许探索的一种方法是使用生成器,将解析链的位向下传递,直到得到一个非函数值。

这不是一个非常严肃的建议,但是一个可行的建议:

var update = pipe()(removeDashes >> removeParens >> removeSpaces);

update("(123) 456-7890"); //=> "1234567890"
这是基于
管道的此实现的:

var pipe = function() {
    var queue = [];
    var valueOf = Function.prototype.valueOf;
    Function.prototype.valueOf = function() {
        queue.push(this);
        return 1;
    };
    return function() {
        Function.prototype.valueOf = valueOf;
        return function(x) {
            for (var i = 0, val = x, len = queue.length; i < len; i++) {
                val = queue[i](val);
            }
            return val;
        }
    };
};
var pipe=function(){
变量队列=[];
var valueOf=Function.prototype.valueOf;
Function.prototype.valueOf=函数(){
排队。推(这个);
返回1;
};
返回函数(){
Function.prototype.valueOf=valueOf;
返回函数(x){
对于(var i=0,val=x,len=queue.length;i

您可以在我的演讲中看到更多内容。

如果您想了解JavaScript中的函数编程,我建议您使用下划线、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的Functional JavaScript也是深入研究这种编程风格的好资源

您可以在一行中创建管道函数,具有良好的可读性:

const pipe = (...fns) => fns.reduce((v, f) => v.constructor === Function ? v() : f(v));
它将以这种方式使用:

var numResult = pipe('(123) 456-7890', removeDashes, removeParens, removeSpaces);
var管道=(…fns)=>fns.reduce((v,f)=>v.constructor==函数?v():f(v));
功能移除灰烬(str){
返回str.replace(/-/g');
}
功能删除参数(str){
返回str.replace(/\(|\)/g',);
}
函数RemoveSpace(str){
返回str.replace(/\s/g');
}
console.log(
'结果:',管道('(123)456-7890',移除灰,移除帕伦斯,移除空间)

);将这些函数添加到字符串的原型中。你可以用链式的方式调用它们。链式编程与函数式编程完全不同。@torazaburo是的,我想我要找的是管道而不是链式编程。Lodash有一个管道函数,看起来像是closestRamda.js管道或compose函数,可用于执行此活动。假设您打算推广向字符串原型添加方法,您至少应该使用
Object.defineProperty(String.prototype,'removeParens',…)
这样它们就不会被枚举。这样做很有效,但我一直在寻找更多的管道而不是链接(我的错误)这很有趣,但对我来说,它的可读性不如仅仅打开包装。谢谢@SkinnyG33k我只是提供了一个不同的选择。使用原型的版本可以工作,但是如果原型发生了变化,它可能会把东西弄脏。除此之外,原型更优越。这可以工作,但我正在寻找更多的管道而不是链接(我的错误)@skinyg33k检查我想这可以修改为允许
管道('(123)456-7890')(RemoveDash>>removeParens>>RemoveSpace);//=>'1234567890'
,甚至可能自动curry它以允许任何一种样式。但这总让人觉得更像是一个把戏,而不是生产代码。那些宏非常漂亮!我在下面的回答中使用了下划线的mixin和chain。足够近,我不必在fns中使用