【问题标题】:NodeJS output is function instead of printed stringsNodeJS 输出是函数而不是打印的字符串
【发布时间】:2020-03-11 11:23:27
【问题描述】:

我无法在 NodeJS 中打印正确的结果,为什么我的代码没有以正确的方式打印字符串?我觉得 console.log 根本没有被调用。为什么我会得到:

[Function]
[Function]
[Function]
[Function]

预期结果:

Tigrou (buddy of Spider) was here!
Spider (buddy of Tigrou) was also here!
Tigrou (buddy of Spider) are in a boat...
1 (buddy of 2)3

我认为可行的代码:

function build_sentence(...args)
{
    var i = 0
    var s = ""
    for (let arg of args)
    {
        if (i == 1)
        {
            i++
            s += "(buddy of " + arg + ") "
        }
        else
        {
            s += arg + " "
            i++
        }
    }
    return s
}

function mycurry(build_sentence)
{
    return function(...args)
    {
        if (!args)
        {
            return build_sentence();
        }
        else
        {
            return mycurry(build_sentence.bind(this, ...args))
        }
    }
}

const curried = mycurry(build_sentence);
console.log(curried("Tigrou")("Spider")(" was here!"))
console.log(curried("Spider")("Tigrou")(" was also here!"))
console.log(curried("Tigrou", "Spider", " are in a boat... "))
console.log(curried(1)(2, 3))

【问题讨论】:

  • 您正在传递一个函数(由您提供的输出理解),因此您必须调用该函数才能真正从中获取您想要的值。
  • 是的,我在最后 5 行调用了函数

标签: javascript node.js function printing arguments


【解决方案1】:

这是一个完整的工作解决方案(字符串间距除外)

const build_sentence_n_params = 3;

function build_sentence(...args)
{
    var i = 0
    var s = ""
    for (let arg of args)
    {
        if (i == 1)
        {
            i++
            s += "(buddy of " + arg + ") "
        }
        else
        {
            s += arg + " "
            i++
        }
    }
    return s
}

// A generic n-parameter curry helper, that returns fn return value
// after n-parameters given, and continues currying with more parameters.
// Note that in this configuration, the caller would also need
// to know how many parameters to give before a value is returned.
function ncurry(fn, n)
{
    // Note that we have to return an outer function here, rather than just
    // returning `curry` function directly, so `params` is unique for each
    // initial call to `curried`.
    return function(...args) {    
        // Initial arguments (note: we can use this array without copy, since
        // rest params will always be a new array)
        const params = args;
        // This function contains the return logic without having to duplicate it below
        function next() {
            // If we have all params, call the given function, otherwise
            // return the curry function again for more parameters
          return !n || params.length >= n ? fn.call(null, ...params) : curry;
        }
        // The outer function is only called once, but this curry
        // function will be called for each additional time.
        function curry(...args) {
            // Accumulate additional arguments
            params.push(...args)
            return next();
        };
        return next();
    };
}

function mycurry(build_sentence)
{
    // Call the generic n-parameter curry helper to generate
    // a specific curry function for our purposes.
    return ncurry(build_sentence, build_sentence_n_params);
}

const curried = mycurry(build_sentence);
console.log(curried("Tigrou")("Spider")(" was here!"))
console.log(curried("Spider")("Tigrou")(" was also here!"))
console.log(curried("Tigrou", "Spider", " are in a boat... "))
console.log(curried(1)(2, 3))

【讨论】:

  • 你必须有一些方法来区分每次调用和最终调用。您可以使用上面的内容,它正在寻找没有参数的最终调用(除了使用!args 而不是!args.length 的错误),但这当然需要您添加到console.log在没有参数的情况下进行另一个最终调用(即()),您说在这种情况下不允许这样做。您可以在每个参数的末尾查找特定类型甚至标点符号(例如句点、感叹号),如果存在,则结束 curry 并返回最终值。
【解决方案2】:

你的方法调用很混乱,所以我冒昧地简化了你的代码。

如果您运行以下命令:

 const curried = build_sentence("Tigrou", "Spider", " was here!");
 console.log(curried);

你会得到你想要的输出:

Tigrou(Spider 的好友)来了!

你为什么使用 mycurry 方法超出了我的理解。

在调试你的代码时,这句话已经建立在第一次调用的基础上,接下来的调用并不是真正的内部函数调用。

【讨论】:

  • 其实我是用它来写一个函数来curryfies另一个函数。因此,我只想修改这两个函数,而不是修改我调用它们的方式。 mycurry 方法在哪里表现不好?
【解决方案3】:

关于我们代码的主要问题是!args 始终为假,因为[] 到布尔也是true

你必须使用!args.length。但是,您应该为您的 curried 函数用法添加一个额外的调用,例如 curried(1)(2, 3)()

另一种方法是比较所需参数的柯里化函数数 (build_sentence.length) 和传递的参数数 (args.length),但它不适用于传播场景。

更新:

ex.1 - 使用 Function.prototype.length 属性

const curry = fn => 
  (...args) => 
    fn.length <= args.length 
      ? fn(...args) 
      : curry(fn.bind(this, ...args));

const func1 = (a, b, c) => `${a},${b},${c}`;
const func2 = (...args) => args.join(',');

console.log(curry(func1)(1,3)(4));
console.log(curry(func1)(1,3,4));
console.log(curry(func1)(1)(3)(4));

console.log(curry(func2)(1));

在这种情况下,currying 对于func1(具有可枚举参数的函数)可以正常工作,因为func1.length = 3。但是对于func2 - func2.length = 0,所以(curry(func1)) 将在之后执行第一次打电话。

ex.2 - 使用传递的参数数量

const curry = fn => 
  (...args) => 
    !args.length 
      ? fn() 
      : curry(fn.bind(this, ...args));
      
const func = (...args) => args.join(',');

console.log(curry(func)(1)(2,3,4)(5)());

在这种情况下,函数柯里化只会返回 fn 执行的结果,当没有参数调用时。但是它会正确处理无数的咖喱函数参数。

【讨论】:

  • 没有更简单的解决方案吗?你能给我一个工作的例子吗?我无法理解您的解释,尤其是“传播场景”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 2020-09-03
  • 2017-09-16
  • 2016-05-07
  • 1970-01-01
  • 2020-04-28
  • 2014-12-14
相关资源
最近更新 更多