Pull to refresh
32
0

Разработчик

Send message
Это меня подтолкнуло на такую мысль: а может абстрагируемся еще больше, и отбросим арифметические операции этого "интэграл"

Не совсем так, числа в кодировке Черча это как раз один из вариантов реализации натуральных чисел, так что уровень абстракции тут ниже. Type class это просто требования к типу — функция опирающаяся на такое требование будет работать с любым типом, в том числе и с числами Черча (хотя конечно натуральные числа у`же чем целые, которые описывает Integral)

Опять громкое название и незаметный дисклеймер в конце статьи. Систему нельзя проектировать исходя из устройства базы данных. Апи к базе данных — возможно.

Увы, Ordering.orElse появился только в 13 скале, мой код на 12

Если необходимо формировать порядок полей в рантайме, то я бы предпочел вместо объявления объектов на каждое поле объявить мапу Map[String, SortField] — все равно поля вероятно прийдут в виде строк.


Делать отдельные кейсы для Asc/Desc/Keep мне кажется легким оверинжинирингом когда можно обойтись Order(asc: Boolean, nullsFirst: Boolean) или Option[Order] если очень нужен Keep.


sealed trait SortField[E]
object SortField {
  case class Optional[E, T](field: E => Option[T], order: Ordering[T])
    extends SortField[E]

  case class Mandatory[E, T](field: E => T, order: Ordering[T])
    extends SortField[E]

  def apply[E, T: Ordering](f: E => T): SortField[E] =
    Mandatory(f, Ordering[T])
  def optional[E, T: Ordering](f: E => Option[T]): SortField[E] =
    Optional(f, Ordering[T])
}

case class SortOrder(asc: Boolean = true, nullsFirst: Boolean = true)

def orderBy[E](fields: (SortField[E], SortOrder)*): Ordering[E] = {
  def initial = Ordering.by[E, Int](_ => 0)
  def direction[T](ordering: Ordering[T], asc: Boolean) =
    if (asc) ordering else ordering.reverse

  val comparator = fields
    .map {
      case (SortField.Mandatory(field, ordering), SortOrder(asc, _)) =>
        direction(Ordering.by(field)(ordering), asc)

      case (SortField.Optional(field, ordering), SortOrder(asc, true)) =>
        Ordering.by(field)(Ordering.Option(direction(ordering, asc)))

      case (SortField.Optional(field, ordering), SortOrder(asc, false)) =>
        val order = direction(Ordering.Option(direction(ordering, !asc)), asc = false)
        Ordering.by(field)(order)
    }
    .foldLeft(initial: Comparator[E])(_ thenComparing _)
  Ordering.comparatorToOrdering(comparator)
}

Нет, должно быть cats(_.owner)(nullsLast) так как nullsLast заменяет собой неявный порядок по-умолчанию.


Что вы имеете в виду говоря про "перебор"?

Если кодировать порядок в АДТ не является самоцелью все эти требования легко удовлетворить двумя функциями:


  def cats[T: Ordering](f: Cat => T): Ordering[Cat] = Ordering.by(f)

  def nullsLast[T](implicit t: Ordering[T]): Ordering[Option[T]] = Ordering.Option(t.reverse).reverse

И то, первая нужна только чтобы не указывать типы вручную.


В результате нужный порядок описывается так:


cats(_.breed) thenComparing 
cats(_.age).reversed thenComparing 
cats(_.owner)(nullsLast)

Чем в вашем понимании отличается Event Sourcing от Службы с открытым протоколом?

Рекомендация избегать исключений так как они ухудшают производительность это преждевременная оптимизация — вполне вероятно в вашем проекте полный отказ от них не повысит производительность и на 2%.


С другой стороны приведённый пример с возвратом пустой строки противоречит второму совету — повышать понятность кода: пустая строка неотличима от реального имени и такой метод может привести к трудноуловимым ошибкам.


Подобный подход имеет место и даже имя — https://ru.m.wikipedia.org/wiki/Null_object_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F), но использовать его нужно явно и осторожно.


В данном случае функциональный подход рекомендует не просто отказаться от исключения, а явно отобразить исключение в возвращаемом значении, например используя Optional.

Это возможно, только если условие res.isEmpty() действительно всегда истинно!
Вот это не совсем верно — условие не полное, так как на самом деле это возможно если cur =! -1 || res.isEmpty()
То есть строчка 'C' действительно недостижима, а 'B' при этом может выполняться. Это возможно, только если условие res.isEmpty() действительно всегда истинно!

Не совсем так, на самом деле всегда истинно cur =! -1 || res.isEmpty(), т.е. как только список перестает быть пустым cur никогда не становится -1, а пока он -1 список пуст.


Хорошо, что статический анализатор находит ошибку в плохом коде, плохо что после исправления ошибки код остается плохим.

Да, функционал одновременно и рискованный и мощный. Многие варианты использования имплиситов неуместны, а неявные преобразования и вовсе будут исключены из языка. С другой стороны этот механизм позволяет реализовать очень интересный механизм — автоматический вывод структур. Например если существует json формат для чисел и строк, и показано как строить форматы для списков и мап, то формат для Map[String, Seq[Int]] выводится автоматически и на стадии компиляции. При этом это не вшито в библиотеку json, а работает для любых типов.

Вот тут сам автор языка очень хорошо описывает основные случаи использования (осторожно, антимонгольский): https://youtu.be/br6035SKu-0

Когда код простой, можно и в процедурном стиле написать, то, что бэк на ноде выглядит функционально это скорее особенность ноды — в той же java обычный бэкэндщик будет вызывать блокирующие процедуры.
Что касается переиспользования дивов — реакт с его функциональным подходом давно так делает, работа же с ивентами без стримов быстро превращается в спагетти.

Поправлю, по оси x доля ошибок в датасете, по оси у — время выполнения (в абстрактных попугаях, так как зависит от окружения)

Не jmh единым

Ну, теоретически такое было возможно и до 8 версии, просто выглядело более громоздко, но та же IDEA это скрывала

Я не говорю про библиотеки, с ними можно все, стандартная библиотека ни в Java 8 ни в Java 11 не поощряет такой подход

Конечно качественно мы имеем две категории — исключения и АТД, но поскольку таких типов в Scala несколько интересно не только сравнить эти две категории, но и несколько разных подходов к обработке ошибок с помощью АТД.
Исключения без трейса это интересный кандидат, пожалуй добавлю его к сравнению.

В Java к сожалению ADT почти не используются и даже стандартный Optional не рекомендуется использовать в интерфейсах и передавать между методами.

Information

Rating
Does not participate
Location
Украина
Date of birth
Registered
Activity