以函数式协变方式使用 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.js
、b.js
、c.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.prototype
、Array.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的主要内容,如果未能解决你的问题,请参考以下文章