应用于函数样式的字符串的函数序列

时间:2015-08-31 08:51:57

标签: javascript functional-programming

我试图理解在实践中使用JavaScript中的功能样式的方法。我已经创建了一组简单的函数来处理字符串,但我觉得我在概念上做错了,因为它看起来就像命令式样式,即使我不改变输入并且不改变应用程序内部的状态功能

以下是它的外观:

var LineParser = require('../modules/LineParser');
var inputLine = 'A line with     multiple          spaces';
var outputLine = LineParser().formatSpaces(inputLine);
//  'A line with multiple spaces'
outputLine = LineParser().capitalize(outputLine);
//  'A Line With Multiple Spaces'
outputLine = LineParser().formatSomethingElse(outputLine);
//  Some more formatting, then do further processing with outputLine

如果我使用回调运行序列,那么当我有10个简单的处理函数时,它会很快变成一组丑陋的嵌套回调函数。

如果我添加方法链接,原型方法的想法也会与功能样式相反,因为链中的函数将取决于先前的状态,而不仅仅取决于它们得到的输入。

我应该怎样做才能让它在功能风格上更好看?

更新:经过深入研究后,我找到了名为Function Composition的主题。它似乎是解决问题的正确方法,也是功能世界的基本内容之一。 这是我用来将多个函数组合成一个函数的函数:

var compose = function () {
    var funcs = arguments;
    return function () {
        var args = arguments;
        for (var i = funcs.length; i-- > 0;) {
            args = [funcs[i].apply(this, args)];
        }
        return args[0];
    };
};

然后我做了一个作文:

var composedFunction = compose(func1, func2, ..., funcn)

从右到左运行,一切正常。

3 个答案:

答案 0 :(得分:0)

您的直排队员似乎有formatSpacescapitalizeformatSomethingElse等方法。你可以做的最简单的事情是将所有这些方法都设置为return this,这样你就可以将这些方法链接起来:

var outputline = LineParser.formatSpaces(inputLine).capitalize().formatSomethingElse()

虽然从外观上看,所有方法都需要一些字符串作为参数,因此您可能需要进行一些实现更改,例如在给定的情况下将字符串保存在私有变量中,如果没有参数则从变量中提取它给出了。

答案 1 :(得分:-1)

如果你想要异步编程,但是你不喜欢嵌套的回调,你考虑过async lib吗? 你可以这样:

var LineParser = require('../modules/LineParser');
var inputLine = 'A line with     multiple          spaces';

async.waterfall([
    function(callback) {
        var result = LineParser().formatSpaces(inputLine);
        callback(null, result);
    },
    function(arg1, callback) {
        var result = LineParser().capitalize(arg1);
        callback(null, result);
    },
    function(arg1, callback) {
        var result = LineParser().formatSomethingElse(arg1);
        callback(null, result);
    }
], function (err, result) {
    // retrieve the final string
});
如果你将LineParser方法修改为异步方法,那么

可以变成有用的东西(否则它只会使你的3行更重)

答案 2 :(得分:-1)

功能风格,即我们在Lisp等中看到的纯函数风格如下所示:

var outputline = formatSomethingElse(capitalize(formatSpaces(inputline)));

通常,为了便于阅读,它的格式为:

var outputline = formatSomethingElse(
    capitalize(
        formatSpaces(inputline)
    )
);

任何其他形式都不是功能风格。功能样式有点像反向波兰表示法,因为所述操作应该反向读取。实际上,RPN本身就是一种函数式编程语法(由Forth体现)。

有一种风格与功能风格相似:方法链:

var outputline = LineParser(inputline)
    .formatSpaces()
    .capitalize()
    .formatSomethingElse()
    .toString();

与功能样式不同,方法链接按顺序读取。

虽然最着名的链接库jQuery会改变对象的状态,但实际上并不是必需的。以LineParser

的以下简单实现为例
function LineParser (text) {
    return {
        text: text,
        toString: function () {return this.text},
        capitalize: function () {
            // return a new object instead of "this"
            return {
                text : _capitalize(this.text),
                toString : this.toString
            }
        }
    }
}