В Win-Vector есть очень мощный новый пакет от ученых гениальных данных (люди, которые делали vtreat
, seplyr
и replyr
), называемые cdata
. Он реализует принципы «скоординированных данных», описанные в в этом документе , а также в этом сообщении в блоге . Идея заключается в том, что независимо от того, как вы организуете свои данные, должно быть возможно идентифицировать отдельные точки данных с помощью системы «координат данных». Вот отрывок из недавнего сообщения в блоге от John Mount:
Вся система основана на двух примитивах или операторах cdata :: moveValuesToRowsD () и cdata :: moveValuesToColumnsD (). Эти операторы имеют сводную, разворотную, однострочную кодировку, транспонирование, перемещение нескольких строк и столбцов и многие другие преобразования как простые частные случаи.
Легко написать много разных операций в терминах примитивов cdata. Эти операторы могут работать как в памяти, так и в больших масштабах данных (с базами данных и Apache Spark, для больших данных используются варианты cdata :: moveValuesToRowsN () и cdata :: moveValuesToColumnsN ()). Трансформации управляются таблицей управления, которая сама является диаграммой (или изображением) преобразования.
blockquote>Сначала мы создадим контрольную таблицу (см. сообщение в блоге для получения подробной информации), а затем выполнить перемещение данных из строк в столбцы.
library(cdata) # first build the control table pivotControlTable <- buildPivotControlTableD(table = dat1, # reference to dataset columnToTakeKeysFrom = 'numbers', # this will become column headers columnToTakeValuesFrom = 'value', # this contains data sep="_") # optional for making column names # perform the move of data to columns dat_wide <- moveValuesToColumnsD(tallTable = dat1, # reference to dataset keyColumns = c('name'), # this(these) column(s) should stay untouched controlTable = pivotControlTable# control table above ) dat_wide #> name numbers_1 numbers_2 numbers_3 numbers_4 #> 1 firstName 0.3407997 -0.7033403 -0.3795377 -0.7460474 #> 2 secondName -0.8981073 -0.3347941 -0.5013782 -0.1745357
Мультиметоды более мощные и дорогие,
используют протоколы, когда они достаточны , но если вам нужно отправить на основе фазы луны, как видно из Марса, то многоточие ваш лучший выбор.
Существуют протоколы, позволяющие простым вещам оставаться простыми и предоставлять способ для клоувера генерировать очень похожий байт-код, который эквивалент java. Похоже, что большинство людей используют протоколы большую часть времени. Я использую multimethods, когда мне нужно отправлять более одного аргумента, хотя я должен признать, что это только один раз, и полные isa
иерархии используются еще реже (по мне). поэтому вкратце используйте Multimethods, когда они вам понадобятся
лучший пример В моей экспирации прямо в начале, в core.clj
Мне нравятся мультиметоды, когда вам не нужна иерархия классов. Например, если у вас есть база данных мультимедиа, и ваши записи похожи на {:media-type :video, :bytes ...}
, то вы можете иметь мультиметод
(defmulti make-grayscale :media-type)
. Затем вы можете сделать различные
; in video.clj
(defmethod make-grayscale :video [record]
(ffmpeg ... (:bytes record))
; in photo.clj
(defmethod make-grayscale :photo [record]
(imagemagick ... (:bytes record))
. Таким образом, вы может избежать наличия центрального выражения cond
, поэтому вы получаете модульность классов. Но вам не нужно проходить всю эту шаблонную иерархию классов «оболочка», которая для меня - это проклятие, которое нужно оставить для мира Java. Мультиметоды - это функции только и для меня больше clojuresque.
Как упоминает Артур, мультиметоды более мощные и дорогие. В самом деле, протоколы можно рассматривать как частный случай mutlimethods, где функция отправки class
. Конечно, на самом деле это не так, поскольку протоколы - это больше.
Если вам нужно отправить что-то, отличное от класса первого аргумента, вам нужно будет использовать мультиметод или редизайн , Диспетчерский тип является хорошим вариантом для протоколов.
Протокол и мультиметоды являются взаимодополняющими и предназначены для немного разных вариантов использования.
В общем, мой совет - использовать протоколы, если у вас нет конкретного случая, требующего многоточия.
Случай, когда вы можете потребовать многоточие, выглядит примерно так:
(defn balance-available? [amount balance] (> balance amount))
(defmulti withdraw balance-available?)
(defmethod withdraw true [amount balance]
(- balance amount))
(defmethod withdraw false [amount balance]
(throw (Error. "Insufficient balance available!")))
Обратите внимание, что вы не можете использовать протоколы здесь по обоим причинам: