CLojure: функции высшего порядка против протоколов против мультиметодов

Есть много протоколов против сравнения мультиметодов, но почему бы не использовать функции более высокого порядка? Давайте рассмотрим пример: у нас есть некоторые данные (например, запись). И у нас есть методы сериализации и десериализации. Скажем, мы хотим сохранить его в файл, в json и в базу данных. Должны ли мы создать протокол с именем SerializationMethod и записи с именем database, json, файл, который их реализует? Это выглядит как взломать создание записей только для использования протокола. Второе решение - multimethod - может взять строковый параметр с выходом сериализации и решить, как это сделать. Но я не уверен, что это правильный путь... И третий способ - написать функцию сериализации, а затем передать туда данные и функцию сериализации. Но теперь я не могу назвать метод сериализации и десериализации с тем же именем (пример json fo):

(defn serialize [method data]
  (method data))

(defn json[data]
  (...))

Вопрос в том, как я могу (или как я) сделать это. Есть ли более общий способ с функцией более высокого порядка? Или, может, я чего-то не понимаю? Это мои первые шаги с clojure, поэтому, пожалуйста, будьте терпимы.

1 ответ

Решение

Преобразование в JSON отличается от записи в базу данных или файл, поскольку последние являются операциями ввода-вывода, а первое - чистым преобразованием данных. Имея это в виду, я бы не рекомендовал реализовывать их под одним и тем же интерфейсом.

Теперь, предполагая, что у вас были различные реализации сериализации, скажем, json и fressian, было бы неплохо реализовать их в каждой структуре данных, которую вы хотите (де -/) сериализовать. Ваше замечание, что это будет взломом, верно. Если говорить более кратко, запись будет ограничена сериализацией (де -/) только с одной реализацией.

Вместо этого было бы более эффективно иметь различные сериализаторы, каждый из которых реализует один и тот же интерфейс:

(defrecord JSONSerializer []
  SerializationMethod
  (serialize [this data] ...)
  (deserialize [this data] ...))

(defrecord FressianSerializer []
  SerializationMethod
  ...)

Таким образом, мы получаем несколько объектов сериализатора, которые могут быть переданы функциям, которым он нужен. Эти функции не должны быть связаны с реализацией.

Могут ли быть переданы функции более высокого порядка?

(defn do-something 
  [params serialize deserialize]
  ...)

Это тоже сработало бы. Однако обратите внимание, что этот стиль может быстро выйти из-под контроля. Например Рассмотрим сценарий, в котором должна быть написана функция, которая десериализует данные из одного формата и сериализует их в другой.

Другие вопросы по тегам