Как и почему используется defmulti и defmethod? и каковы преимущества? - программирование
Подтвердить что ты не робот

Как и почему используется defmulti и defmethod? и каковы преимущества?

Я хотел бы знать, почему используются defmulti и defmethod? Каковы преимущества? И как вы его используете? Пожалуйста, объясните, что происходит в коде.

4b9b3361

Ответ 1

В "общих терминах" вы бы назвали это if/else на стероидах и в стиле "произвести впечатление", который вы назвали бы им с "динамической отправкой", "полином времени выполнения" и т.д.

Предположим, вы хотите определить функцию "Добавить", которая должна работать для разных типов данных, например, в случае Int, она должна добавить числа, в случае строк она должна конкатцировать строки. Теперь его очень просто реализовать, используя if else, в основном вы проверяете тип аргументов и, если они являются целыми числами, затем добавляйте их, если они являются строками, тогда concat их еще генерирует исключение. Но проблема заключается в том, что если вы хотите добавить поддержку нового типа данных в свою функцию добавления, вам нужно будет изменить функцию добавления, что может быть невозможно в тех случаях, когда вы не выполняете контролировать источник добавления, например, в случае, если он определен в некоторой библиотеке и т.д. defmulti и defmethod позволяет решить эту проблему, добавив новый случай к существующей функции без изменения ее кода.

(defmulti add (fn [a b] [(type a) (type b)]))

add - это имя функции, анонимная функция - это ваш if/else, в основном это будет вызываться в ваших аргументах добавления, и возвращаемое значение этой функции будет проверяться, если есть какая-либо реализация. Теперь давайте реализуем его для Integer.

(defmethod add [Integer Integer] ([a b] (+ a b)))

[Integer Integer] - это регистр сортировки по возвращаемому значению анонимной функции, определенной в defmulti, а затем реализации.

Аналогично мы можем сделать для строк

(defmethod add [String String] ([a b] (str a b)))

Вызов его целыми числами (add (int 1) (int 2))

Вызов со строками (add "hello" "world")

Вызов его с чем-то, что не соответствует нашему if/else. i.e еще не реализация для случая приведет к исключению

Ответ 2

Из того, что я наблюдал после прочтения ответа (и используя приведенный выше пример), также полезно понять следующее:

при выполнении команды:

(add (int 5) (int 2))

Что происходит, так это то, что выполняется 'add defmulti', создавая список:

[Integer Integer]

с созданным, он ищет какой-либо "add defmethod", который идентифицируется с помощью вышеперечисленного списка i.e.:

(add [Integer Integer])

И передает аргументы, которые он получил.

Другой способ определения нескольких методов, чтобы упростить передачу аргументов:

(defmulti add (fn [a b] [(type a) (type b)]))
(defmethod add [Integer Integer] [a b] (+ a b))
(defmethod add [String String] [a b] (str a b))

Затем запустите функцию как:

(add 12 73)

или

(add "thank" "you")