【问题标题】:Use Array.prototype.map in a functional, covariant way以函数式协变方式使用 Array.prototype.map
【发布时间】:2019-06-01 02:27:31
【问题描述】:

假设我有以下输入(与Node 一起使用,但问题更普遍,与节点无关):

  • 目录的绝对路径,叫它dirPathAbs
  • 该文件夹中存在的一些 JS 文件的基本名称数组(称为 namesSeq

例如:

我可能有namesSeq = ['a', 'b', 'c'],它对应于dirPathAbs内的一些a.jsb.jsc.js

问题:

如何以纯函数方式以及协变方式解析文件的路径? (即不必谈论迭代数组的变量。协变可能不是这个词,抱歉)。

我不想要的:

namesSeq.map(base => path.join(dirPathAbs, `${base}.js`));

也没有

namesSeq.map(base => require.resolve(path.join(dirPathAbs, base)));  

也没有

namesSeq.map(base => path.resolve.bind(dirPathAbs)(base));

也没有

const cb = base => path.resolve.bind(dirPathAbs)(base);
namesSeq.map(cb);

我期待这个可以工作

namesSeq.map(path.resolve.bind(dirPathAbs))

但事实并非如此。我认为path.resolve.bind(dirPathAbs) 接收作为输入namesSeq,这是提供给Array.prototype.map 的回调的第三个参数,因为我看到的错误是

TypeError: Path must be a string. Received [ 'a', 'b', 'c' ]

这只是一种让我沮丧的练习,但是自从学习 JS 以来,一整类类似的练习让我很头疼。当谈到this 的绑定方式以及所有这些Function.prototypeArray.prototype 和朋友应该如何使用时,我仍然缺少一些东西。

【问题讨论】:

  • 你为什么不想要这些解决方案?
  • 快速回答是“为了练习”,但我还有另一个原因。我会在几个小时内尝试清楚地制定它。

标签: javascript node.js ecmascript-6 prototype-programming array.prototype.map


【解决方案1】:

你可以在中间添加另一个函数来吃掉那些额外的变量:

 const take = (fn, n) => (...args) => fn(...args.slice(0, n));
 const bind = fn => (...args) => (...args2) => fn(...args, ...args2);

 namesSeq.map(take(bind(path.resolve)(dirPathAbs), 1));

但我没有看到比命名参数有任何优势。

【讨论】:

    【解决方案2】:

    你没有注意Array.map预期的回调。

    看了docs,你会发现方法的语法是这样的:

    var new_array = arr.map(function callback(currentValue[, index[, array]]) {
        // Return element for new_array
    }[, thisArg])
    

    如您所见,它将整个数组传递给回调。这就是您想要的解决方案不起作用的原因。

    不寻求外部库帮助的最佳解决方案(如fp/lodash/)是倒数第二个选项:

    namesSeq.map(base => path.resolve.bind(dirPathAbs)(base));
    

    【讨论】:

      【解决方案3】:

      我认为可能有一个关于namesSeq 的假设,这部分是错误的。这是一个非常简单的示例,它或多或少地遵循您正在做的事情。您可以在运行 sn-p 时看到它按预期工作:

      function mockResolve(input) {
        console.log(input)
        return input * 2;
      }
      
      var scopeObject = {
        sequence: [1, 2, 3]
      };
      
      var accessSequence = scopeObject.sequence;
      var mapping = accessSequence.map(mockResolve.bind(scopeObject));
      console.log(mapping);

      namesSeq 只是一个包含这些文件字符串的数组吗?在不确定的情况下,我猜测它可能是一个包含文件名字符串数组的数组,因此当它需要一个字符串时,字符串数组会出错。

      【讨论】:

        猜你喜欢
        • 2022-11-28
        • 2019-06-07
        • 2014-11-01
        • 2021-10-29
        • 2012-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多