
В этом видео мы с вами рассмотрим такой метод Ramda, как converge.
Итак, у нас есть задача - написать функцию, которая будет проверять, является ли первый элемент массива наибольшим.
Давайте напишем 2 массива
const isValidAr = [6, 3, 4, 5, 2]
const isInvalidAr = [3, 4, 6, 1]
console.log(isFirstElementBiggest(isValidAr))
console.log(isFirstElementBiggest(isInvalidAr))
Соответственно, при вызове нашей функции на первый массив, она должна вернуть true, а на второй false.
На чистом javascript мы могли бы написать функцию вот так
const isFirstElementBiggest = elements =>
elements[0] === elements.sort((a, b) => b - a)[0]
На вход мы получаем массив, берем из него первый элемент и сравниваем будет ли он равен первому элементу, если этот же массив упорядочить по убыванию.
Если мы посмотрим в браузер, то все работает. Как же мы можем улучшить этот код? Обратите внимание, что мы дважды делаем операции с elements. Если мы делаем какие-то операции с одной и той же переменной несколько раз, чтобы получить результат, то это верный признак того, что мы можем применить converge из Ramda.
В чем идея converge? Мы можем вызвать несколько разных функций на одни и те же данные, и потом применить какую-то функцию на результат этих функций.
В нашем случаем мы можем написать функцию, которая возьмет первый элемент массива, и функцию, которая отсортирует массив и также возьмет первый элемент. А потом сравнить результат этих двух функций.
Давайте попробуем.
const isFirstElementBiggest = R.converge(R.equals, [
])
Converge конечно же каррируется, так что мы можем убрать аргумент. Первым аргументом converge мы передаем R.equals. Это та функция, которая будет вызвана на результаты массива функций.
Первой функцией у нас будет нахождение первого элемента
const isFirstElementBiggest = R.converge(R.equals, [
elements => elements[0]
])
А второй функцией сортировка и нахождение первого элемента
const isFirstElementBiggest = R.converge(R.equals, [
elements => elements[0],
elements => elements.sort((a, b) => b - a)[0]
])
Если мы посмотрим в браузер, то мы получаем все тот же результат.
Мы можем улучшить этот код еще немного, ведь в Ramda уже есть функция, чтобы найти первый элемент. Это функция head.
const isFirstElementBiggest = R.converge(R.equals, [
R.head,
elements => elements.sort((a, b) => b - a)[0]
])
И мы можем написать head во второй функции тоже
const isFirstElementBiggest = R.converge(R.equals, [
R.head,
elements => R.head(elements.sort((a, b) => b - a))
])
Теперь мы можем применить сортировку по убыванию из Ramda.
const isFirstElementBiggest = R.converge(R.equals, [
R.head,
elements => R.head(R.sort(R.descend(R.identity))(elements))
])
Итак:
Этот код стало достаточно сложно читать из-за большой композиции. Мы можем, с помощью метода compose, сделать этот код читабельнее и он будет point free.
const isFirstElementBiggest = R.converge(R.equals, [
R.head,
R.compose(R.head, R.sort(R.descend(R.identity)))
])
Если мы посмотрим в браузер, то все по прежнему работает. Так как нам нужно считывать код с сортировкой для того, чтобы понять что она делает внутри, давайте вынесем сортировку в переменную.
const sortByBiggestFirst = R.sort(R.descend(R.identity))
const isFirstElementBiggest = R.converge(R.equals, [
R.head,
R.compose(R.head, sortByBiggestFirst)
])
Итак еще раз:
Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.