Используйте Array.prototype.map функциональным ковариантным способом - PullRequest
0 голосов
/ 06 января 2019

Скажем, у меня есть следующий вход (для использования с Node, но проблема носит более общий характер и не связана с узлом):

  • Абсолютный путь к каталогу, назовите его dirPathAbs
  • Массив базовых имен (назовите его namesSeq) некоторых файлов JS, которые существуют в этой папке

Например:

У меня может быть namesSeq = ['a', 'b', 'c'], что соответствует некоторым a.js, b.js, c.js внутри dirPathAbs.

Проблема:

Как мне разрешить пути к файлам чисто функциональным способом , но также ковариантным образом ? (т.е. без необходимости когда-либо говорить о переменной, которая повторяет массив. Ковариант может не подходить для этого, извините ).

Чего я не хочу:

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 и друзья должны использоваться.

Ответы [ 3 ]

0 голосов
/ 06 января 2019

Вы не обращаете внимание на обратный вызов, ожидаемый 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));
0 голосов
/ 06 января 2019

Я думаю, что может быть предположение о namesSeq, которое здесь частично ошибочно. Вот очень простой пример, который более или менее соответствует тому, что вы делаете. Когда вы запускаете фрагмент, вы можете видеть, что он работает как положено:

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 просто массивом, содержащим строки этих файлов? Не зная наверняка, я предполагаю, что это может быть массив, содержащий массив строк с именами файлов, отсюда и ошибка массива строк, когда он ожидал строку.

0 голосов
/ 06 января 2019

Вы можете добавить еще одну функцию в середине, чтобы съесть эти дополнительные переменные:

 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));

но я не вижу каких-либо улучшений в отношении именованного параметра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...