Чи назвав Клоджуре аргументи? Якщо так, чи можете ви навести невеликий приклад цього?
Чи назвав Клоджуре аргументи? Якщо так, чи можете ви навести невеликий приклад цього?
Відповіді:
У Clojure 1.2 ви можете деструктурувати rest
аргумент так само, як і карту. Це означає, що ви можете виконувати іменовані позиційні аргументи ключових слів. Ось приклад:
user> (defn blah [& {:keys [key1 key2 key3]}] (str key1 key2 key3))
#'user/blah
user> (blah :key1 "Hai" :key2 " there" :key3 10)
"Hai there10"
user> (blah :key1 "Hai" :key2 " there")
"Hai there"
user> (defn blah [& {:keys [key1 key2 key3] :as everything}] everything)
#'user/blah
user> (blah :key1 "Hai" :key2 " there")
{:key2 " there", :key1 "Hai"}
Все, що ви можете зробити під час деструктуризації карти Clojure, можна зробити у списку аргументів функції, як показано вище. Включаючи використання: або для визначення параметрів за замовчуванням для таких аргументів:
user> (defn blah [& {:keys [key1 key2 key3] :or {key3 10}}] (str key1 key2 key3))
#'user/blah
user> (blah :key1 "Hai" :key2 " there")
"Hai there10"
Але це в Clojure 1.2. Крім того, у старих версіях ви можете зробити це, щоб імітувати те саме:
user> (defn blah [& rest] (let [{:keys [key1 key2 key3] :or {key3 10}} (apply hash-map rest)] (str key1 key2 key3)))
#'user/blah
user> (blah :key1 "Hai" :key2 " there")
"Hai there10"
і це працює, як правило, однаково.
А також ви можете мати позиційні аргументи, які стоять перед аргументами ключового слова:
user> (defn blah [x y & {:keys [key1 key2 key3] :or {key3 10}}] (str x y key1 key2 key3))
#'user/blah
user> (blah "x" "Y" :key1 "Hai" :key2 " there")
"xYHai there10"
Вони не є обов’язковими та повинні бути надані.
Ви можете фактично деструктурувати rest
аргумент, як будь-яку колекцію Clojure.
user> (defn blah [& [one two & more]] (str one two "and the rest: " more))
#'user/blah
user> (blah 1 2 "ressssssst")
"12and the rest: (\"ressssssst\")"
Ви можете робити подібні речі навіть у Clojure 1.1. Деструктуризація стилю карти для аргументів ключових слів увійшла лише в 1.2.
На додаток до чудової відповіді Рейнеса, у clojure-contrib також є макрос, який полегшує життя:
користувач => (використовувати '[clojure.contrib.def: лише [defnk]]) нуль користувач => (defnk foo [ab: c 8: d 9] [а Б В Г]) # 'користувач / foo користувач => (foo 1 2) [1 2 8 9] користувач => (foo 1 2 3) java.lang.IllegalArgumentException: Не вказано значення для ключа: 3 (NO_SOURCE_FILE: 0) користувач => (foo 1 2: c 3) [1 2 3 9]
Починаючи з версії Clojure 1.8, підтримка ключових слів все ще здається трохи захопленою .
Ви можете вказати такі аргументи ключових слів:
(defn myfn1
"Specifying keyword arguments without default values"
[& {:keys [arg1 arg2]}]
(list arg1 arg2))
Приклади його виклику:
(myfn1 :arg1 23 :arg2 45) --> evaluates to (23 45)
(myfn1 :arg1 22) --> evaluates to (22 nil)
Якщо ви хочете вказати значення за замовчуванням для цих аргументів ключового слова:
(defn myfn2
"Another version, this time with default values specified"
[& {:keys [arg1 arg2] :or {arg1 45 arg2 55}}]
(list arg1 arg2))
Це робить очікувану річ у другому випадку:
(myfn2 :arg1 22) --> evaluates to (22 55)
У кожній частині кожної мови є плюси і мінуси, але лише для порівняння, ось як ви робите ті самі речі у Common Lisp:
(defun myfn3
(&key arg1 arg2)
"Look Ma, keyword args!"
(list arg1 arg2))
(defun myfn4
(&key (arg1 45) (arg2 55))
"Once again, with default values"
(list arg1 arg2))
Ви, мабуть, маєте на увазі іменовані параметри ? Вони не доступні безпосередньо, але ви можете використовувати цей підхід до векторів, якщо хочете, що може дати вам те, що ви хочете.
У RosettaCode є більш глибоке пояснення того, як це зробити за допомогою деструктуризації.