#10 Пишем условия с when и unless в Ramda

poster
В этом видео мы разберем такие методы в Ramda, как when и unless.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

В этом видео мы разберем такие методы в Ramda, как when и unless.

Давайте напишем метод truncate, который будет обрезать строку, если в ней больше 10ти символов и добавлять три точки. Если же меньше, то просто возвращать строку.

И на javascript мы бы написали как-то так.

const truncate = str => {
  let truncatedStr
  if (str.length > 10) {
    truncatedStr = str.substring(0, 10)
    truncatedStr = `${truncatedStr}...`
  } else {
    truncatedStr = str
  }
  return truncatedStr
}
console.log(truncate('12345'))
console.log(truncate('123456789010'))

Если мы посмотрим в браузер, то все работает правильно. В первом случае строка возвращается так, как она есть, а в втором мы берем первые 10 символов и добавляем три точки.

Что в этом коде плохо? Он написан в декларативном стиле, его сложно считывать и мы могли бы написать лучше используя Ramda.

В Ramda есть метод when, который первым аргументом принимает функцию, которая возвращает true/false, а вторым то, что мы сделаем если вернулось true

R.when(
  (data) => true,
  (data) => 1
)(data)

Давайте попробуем переписать наш метод

const truncate = R.when(
  str => str.length > 10,
  R.compose(
    R.join(''),
    R.append('...'),
    R.take(10)
  )
)

В when первым параметром мы передали функцию, которая проверяет больше ли length чем 10. Если да, то мы вызываем R.compose. В нем мы берем первые 10 элементов, но мы получим их в виде массива, потом добавляем в конец массива три точки и джойним.

Если первая функция вернет false, то вторая просто не выполнится.

Этот код выглядит достаточно хорошо, но первую функцию мы могли бы тоже написать point free стилем.

const truncate = R.when(
  R.propSatisfies(R.gt(R.__, 10), 'length'),
  R.compose(
    R.join(''),
    R.append('...'),
    R.take(10)
  )
)

console.log(truncate('12345'))
console.log(truncate('123456789010'))

Здесь мы используем метод propSatisfies, в который вторым аргументом мы передаем то, что хотим проверить, в данном случае проперти length, а первым функцию, которая будет что-то проверять у этого проперти.

Если мы посмотрим в браузер, то все работает как и раньше.

Метод R.unless в Ramda абсолютно противоположен R.when. Он выполняет вторую функцию, если первая вернула false.

const truncate = R.unless(
  R.propSatisfies(R.gt(R.__, 10), 'length'),
  R.compose(
    R.join(''),
    R.append('...'),
    R.take(10)
  )
)

console.log(truncate('12345'))
console.log(truncate('123456789010'))

Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Jin zakk
10 месяцев назад
Добрый день, а Вы пробовали соединять R.when с R.forEach или другими циклами? Я попытался сделать это, но у меня некорректно работает условие(R.when): const arrayMale = { woman1: true, man1: false, man2: true, woman2: false } var printKeyConcatValue = (value, key) => R.when( R.always(value), R.always(console.log(key + ':' + value)) )(value, key); R.forEachObjIndexed(printKeyConcatValue, arrayMale); По идее в первом аргументе(R.always(value)) должна происходить проверка и если value=true, то в консоли стреляет например man1:true, но условие пропускает вообще все. Пробовал ставить вместо R.always(value) это R.equals(value, true), но консоль матерится. Буду благодарен за ответ
monsterlessons
10 месяцев назад
Сигнатура использования when R.when(R.always(value), () => {}) вторый параметром должна идти функция а не R.always. R.forEach я не использую вообще, так как это императивный стиль, который практически никогда не нужен.
Jin zakk
10 месяцев назад
Благодарю за ответ. Подкорректировал код по вашему коменту, а вместо R.always(value) написал R.identity(value) ,и алгоритм стал корректно работать.
Alex Panchuk
1год назад назад
Вроде как str => str.length > 10 лучше читается, чем R.propSatisfies(R.gt(R.__, 10), 'length')
monsterlessons
1год назад назад
Да, согласен.