Jak utworzyć wartość domyślną dla argumentu funkcji w Clojure
Przychodzę z tym:
(defn string->integer [str & [base]] (Integer/parseInt str (if (nil? base) 10 base))) (string->integer "10") (string->integer "FF" 16)Ale to musi być lepszy sposób.
5 answers
Funkcja może mieć wiele podpisów, jeśli podpisy różnią się arytmetyką. Możesz użyć tego do podania wartości domyślnych.
(defn string->integer
([s] (string->integer s 10))
([s base] (Integer/parseInt s base)))
Zauważ, że zakładając, że false
i nil
są uważane za nie wartości, (if (nil? base) 10 base)
można skrócić do (if base base 10)
lub dalej do (or base 10)
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-08 22:10:18
Od Clojure 1.2 [ref można także destrukcję argumentów rest
jako mapę. Pozwala to na nazwanie i podanie domyślnych argumentów funkcji:
(defn string->integer [s & {:keys [base] :or {base 10}}]
(Integer/parseInt s base))
Teraz możesz zadzwonić
(string->integer "11")
=> 11
Lub
(string->integer "11" :base 8)
=> 9
Możesz zobaczyć to w akcji tutaj: https://github.com/Raynes/clavatar/blob/master/src/clavatar/core.clj (na przykład)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-28 20:49:16
To rozwiązanie jest bliższe duchowi oryginalnego rozwiązania , ale nieznacznie czystsze
(defn string->integer [str & [base]]
(Integer/parseInt str (or base 10)))
A podobny wzór który może być przydatny or
w połączeniu z let
(defn string->integer [str & [base]]
(let [base (or base 10)]
(Integer/parseInt str base)))
Podczas gdy w tym przypadku jest to bardziej szczegółowe, może być przydatne, jeśli chcesz mieć wartości domyślne zależne od innych wartości wejściowych . Na przykład rozważmy następującą funkcję:
(defn exemplar [a & [b c]]
(let [b (or b 5)
c (or c (* 7 b))]
;; or whatever yer actual code might be...
(println a b c)))
(exemplar 3) => 3 5 35
To podejście można łatwo rozszerzyć o pracę z nazwanymi argumentami (jak w M. Rozwiązanie gilliara) również:
(defn exemplar [a & {:keys [b c]}]
(let [b (or b 5)
c (or c (* 7 b))]
(println a b c)))
Lub używając jeszcze więcej fuzji:
(defn exemplar [a & {:keys [b c] :or {b 5}}]
(let [c (or c (* 7 b))]
(println a b c)))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-27 22:52:12
Istnieje inne podejście, które warto rozważyć: częściowe funkcje. Są to prawdopodobnie bardziej "funkcjonalne" i bardziej elastyczne sposoby określania wartości domyślnych dla funkcji.
Zacznij od utworzenia (jeśli to konieczne) funkcji, która ma parametr (- Y), który (- E) chcesz podać jako domyślny (- e) jako parametr (- y) wiodący (- E):
(defn string->integer [base str]
(Integer/parseInt str base))
Dzieje się tak, ponieważ Wersja Clojure partial
pozwala podać "domyślne" wartości tylko w kolejności, w jakiej są wyświetlane w funkcji definicja. Po uporządkowaniu parametrów można utworzyć "domyślną" wersję funkcji za pomocą funkcji partial
:
(partial string->integer 10)
W celu wywołania tej funkcji wiele razy można umieścić ją w var używając def
:
(def decimal (partial string->integer 10))
(decimal "10")
;10
Możesz również utworzyć "domyślną lokalną" używając let
:
(let [hex (partial string->integer 16)]
(* (hex "FF") (hex "AA")))
;43350
Podejście funkcji częściowej ma jedną kluczową przewagę nad innymi: konsument funkcji może nadal decydować, co jest domyślne wartość będzie raczej producentem funkcji bez konieczności modyfikowania definicji funkcji . Jest to zilustrowane w przykładzie z hex
gdzie zdecydowałem, że domyślna funkcja {[10] } nie jest tym, czego chcę.
Kolejną zaletą tego podejścia jest to, że można przypisać funkcji domyślnej inną nazwę (dziesiętne, hex, itp.), która może być bardziej opisowa i / lub inny zakres (var, local). Funkcja częściowa może być również mieszana z niektórymi z podejście powyżej w razie potrzeby:
(defn string->integer
([s] (string->integer s 10))
([base s] (Integer/parseInt s base)))
(def hex (partial string->integer 16))
W odpowiedzi Briana na to pytanie Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana, Briana]}Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-26 16:04:46
Możesz również przyjrzeć się (fnil)
https://clojuredocs.org/clojure.core/fnil
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-21 05:17:46