以函数式协变方式使用 Array.prototype.map

Posted

技术标签:

【中文标题】以函数式协变方式使用 Array.prototype.map【英文标题】:Use Array.prototype.map in a functional, covariant way 【发布时间】: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 和朋友应该如何使用时,我仍然缺少一些东西。

【问题讨论】:

你为什么不想要这些解决方案? 快速回答是“为了练习”,但我还有另一个原因。我会在几个小时内尝试清楚地制定它。 【参考方案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 只是一个包含这些文件字符串的数组吗?在不确定的情况下,我猜测它可能是一个包含文件名字符串数组的数组,因此当它需要一个字符串时,字符串数组会出错。

【讨论】:

以上是关于以函数式协变方式使用 Array.prototype.map的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中使用成员函数向量时,有没有办法实现协变返回类型?

协变和逆变

覆盖虚函数协变返回类型(两个指针)

如何检查函数中元素的协变和逆变位置?

覆盖虚函数返回类型不同且在数据结构中不是协变的

深入理解Java泛型协变逆变泛型通配符自限定