Применение карты к аргументу rest функции
1687 просмотра
4 ответа
В Clojure, если у меня есть функция f ,
(defn f [& r] ... )
и у меня есть seq args с аргументами, которые я хочу вызвать f, я могу легко использовать apply :
(apply f args)
Теперь, скажем, у меня есть другая функция g , которая предназначена для принятия любого из ряда необязательных именованных аргументов, то есть, где аргумент rest деструктурируется как карта:
(defn g [& {:keys [a b] :as m}] ... )
Я обычно звоню г, делая что-то вроде
(g :a 1 :b 2)
но если у меня есть карта my-map со значением {: a 1: b 2}, и я хочу «применить» g к my-map - другими словами, получить что-то, что в конечном итоге вызовет приведенный выше вызов тогда я, естественно, не мог использовать apply, так как это было бы эквивалентно
(g [:a 1] [:b 2])
Есть хороший способ справиться с этим? Могу ли я сойти с пути в своем дизайне, чтобы закончить с этим? Лучшее решение, которое я могу найти, было бы
(apply g (flatten (seq my-map)))
но мне точно это не нравится Есть лучшие решения?
РЕДАКТИРОВАТЬ: небольшое улучшение предложенного решения может быть
(apply g (mapcat seq my-map))
который по крайней мере удаляет один вызов функции, но все еще может быть не совсем понятно, что происходит.
Автор: Marxama Источник Размещён: 13.11.2019 11:41Ответы (4)
6 плюса
Я сам наткнулся на эту проблему и в итоге определил функции, ожидающие одну карту. Карта может иметь различное количество пар ключ / значение, и, если она достаточно гибкая, нет необходимости в аргументах & rest. Также нет боли при применении. Делает жизнь намного проще!
(defn g [{:keys [a b] :as m}] ... )
Автор: Michiel Borkent
Размещён: 02.05.2013 08:46
3 плюса
Нет лучшего прямого пути, чем преобразование в последовательность.
Вы сделали. Вы сделали все, что могли.
Просто не очень удобно иметь стиль Common Lisp: ключевые слова arg функции. Если вы посмотрите на код Clojure, то обнаружите, что почти все функции написаны таким образом.
Даже великие RMS не являются их поклонниками
«Одна вещь, которая мне не очень нравится, это аргументы с ключевыми словами (8). Мне они не совсем нравятся. Я сделаю это иногда, но я минимизирую время, когда я это делаю». ( Источник )
В тот момент, когда вам нужно разбить полную хеш-карту на части, чтобы передать их в качестве аргументов, сопоставленных с ключевыми словами, вы должны подвергнуть сомнению свой дизайн функции.
Я обнаружил, что в случае, когда вы хотите передать общие параметры, как :consider-nil true
вы, вероятно, никогда не будете вызывать функцию с хэш-картой {:consider-nil true}
.
В случае, если вы хотите выполнить оценку на основе некоторых ключей хэш-карты, вы в 99% случаев имеете f ([m & args])
объявление.
Когда я начал определять функции в Clojure, я столкнулся с той же проблемой. Однако, подумав больше о проблемах, которые я пытался решить, я заметил, что практически никогда не использую деструкторы в объявлении функций.
Автор: Leon Grapenthin Размещён: 04.05.2013 05:431 плюс
Вот очень упрощенная функция, которую можно использовать в точности так, как она применяется, за исключением того, что последний аргумент (который должен быть картой) будет расширен до: key1 val1: key2 val2 и т. Д.
(defn mapply
[f & args]
(apply f (reduce concat (butlast args) (last args))))
Я уверен, что есть более эффективные способы сделать это, и то, хотите ли вы в конечном итоге оказаться в ситуации, когда вам придется использовать такую функцию, обсуждается, но она действительно отвечает на первоначальный вопрос. В основном, я по-детски доволен именем ...
Автор: Marxama Размещён: 08.05.2013 08:540 плюса
Самое хорошее решение, которое я нашел:
(apply g (apply concat my-map))
Автор: Ernesto
Размещён: 15.10.2017 02:51
Вопросы из категории :
- clojure Есть ли реальный опыт использования программной транзакционной памяти?
- clojure Каков наилучший способ сделать GUI в Clojure?
- clojure Быстрая генерация простых чисел в Clojure
- clojure Что такое закрытый эквивалент идиомы Python "if __name__ == '__main__'"?
- clojure Отображение функции по значениям карты в Clojure
- clojure Clojure: Как вернуться к исключению?
- clojure Compojure HTML Форматирование
- clojure Вызов clojure из Java
- clojure Как я могу обновить векторный элемент в Clojure?
- clojure Какой самый простой способ разобрать числа в clojure?
- clojure Использование javax.servlet.Filter с Compojure
- clojure Как связать нативную библиотеку и библиотеку JNI внутри JAR?
- clojure Проверьте, содержит ли список конкретное значение в Clojure
- clojure Варианты JVM с использованием Leiningen
- clojure Есть ли языковая спецификация для clojure?
- clojure Как генерировать запомненные рекурсивные функции в Clojure?
- clojure Как вы относитесь к примитивным типам Java в Clojure?
- clojure Clojure не ловит NumberFormatException
- clojure Clojure: returning a vector from an anonymous function
- clojure Clojure стиль функции «многопоточность» в Python