Стандарты кодирования Clojure - для вызова функций со многими аргументами - PullRequest
0 голосов
/ 08 февраля 2019

В настоящее время я использую функцию

(def mymap {})

(defn function1 [var1 var2 var3 var4 var5]
  ;calls another functions with all variables.
  (function2 var1 var2 var3 var4 var5)
)

Но так как в ней больше параметров, я хотел бы преобразовать ее в карту перед вызовом функций 2.

(function2((assoc mymap (keyword var1) var1
               (keyword var2) var2
               (keyword var3) var3
               (keyword var4) var4
               (keyword var5) var5 ))
  )

Этоправильный путь?Есть ли у нас лучший способ сделать это (В Java мы используем некоторые объекты в этом сценарии)

1 Ответ

0 голосов
/ 08 февраля 2019

Для аргументов общей функции я всегда иду по порядку от самого большого к наименьшему, либо по размеру, либо по «важности» (несколько субъективно).


Однако, еслиу вас есть более 3 аргументов , я предпочитаю передавать карту, содержащую аргументы и соответствующие имена ключевых слов.

В библиотеке Tupelo Clojure есть несколько инструментов, чтобы упростить эту задачу,Макрос vals->map принимает несколько имен переменных и создает карту из имени переменной (с ключевыми словами) и его значения, например:

  (let [ctx (let [a 1
                  b 2
                  c 3
                  d 4
                  e 5]
              (t/vals->map a b c d e))]
    (is= ctx {:a 1 :b 2 :c 3 :d 4 :e 5})

Макрос with-map-vals выполняет обратное, деконструируя значения карты в локальные переменныеназван в честь своих ключей.Это похоже на деструктуризацию Clojure :keys, но в (IMHO) более естественной форме:

    (let [{:keys [a b c d e]} ctx]    ; Clojure destructing syntax
      (is= [a b c d e] [1 2 3 4 5]))

    (t/with-map-vals ctx [a b c d e]
      (is= [a b c d e] [1 2 3 4 5])
      (is= 15 (+ a b c d e)))

    (t/with-map-vals ctx [b a d c e]  ; order doesn't matter
      (is= [a b c d e] [1 2 3 4 5])
      (is= 15 (+ a b c d e)))

    (t/with-map-vals ctx [b a d]      ; can ignore stuff you don't care about
      (is= [d a b] [4 1 2]))

    (throws?
      (t/with-map-vals ctx [a b z]    ; throws if key doesn't exist
        (println "won't ever get here")))))

Если у вас есть вложенные данные в картах и ​​/ или векторах, вы можете использовать более мощные инструменты destruct и restruct.Вот краткий пример ( из модульных тестов ):

  (let [info  {:a 1
               :b {:c 3
                   :d 4}}
        mania {:x 6
               :y {:w 333
                   :z 666}}]

    (t/it-> (t/destruct [info {:a ?
                               :b {:c ?
                                   :d ?}}
                         mania {:y {:z ?}}] ; can ignore unwanted keys like :x
              (let [a (+ 100 a)
                    c (+ 100 c)
                    d z
                    z 777]
                (restruct-all)))
      (t/with-map-vals it [info mania]
        (is= info {:a 101, :b {:c 103, :d 666}})
        (is= mania {:x 6, :y {:w 333, :z 777}})))

Как видите, знак вопроса ? приведет к разрушению соответствующего значения в переменной с именемдля соответствующего ключевого слова.Также возможно создание явных имен переменных, например:

(dotest
  (let [info  {:a 777
               :b [2 3 4]}
        mania [{:a 11} {:b 22} {:c [7 8 9]}]]
    (let [z ::dummy]
      (t/it-> (t/destruct [info {:a z
                                 :b [d e f]}
                           mania [{:a ?} BBB {:c clutter}]]
                (let [clutter (mapv inc clutter)
                      BBB     {:BBB 33}
                      z       77
                      d       (+ 7 d)]
                  (restruct-all)))
        (t/with-map-vals it [info mania]
          (is= info {:a 77, :b [9 3 4]})
          (is= mania [{:a 11} {:BBB 33} {:c [8 9 10]}]))))))

Это также работает для смешанных карт и векторов:

  (let [data {:a [{:b 2}
                  {:c 3}
                  [7 8 9]]} ]
    (t/destruct [data {:a [{:b p}
                           {:c q}
                           [r s t]]} ]
      (is= [2 3 7 8 9] [p q r s t])))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...