Clojure

マップから使いたいキーバリューペアを抽出し、なおかつデフォルト値もセットしたい

More than 1 year has passed since last update.

Clojureのフレームワークでは、設定値をマップで渡されて、関数内で必要なものを抽出して用いるケースが多いようです。(例:Leiningenのproject.clj。pprintプラグインを使って表示してみます。)

$ lein pprint
Leiningen's classpath: ../src::/usr/local/Cellar/leiningen/2.5.0/libexec/leiningen-2.5.0-standalone.jar
Applying task pprint to []
{:description "test project using lein-zinc",
 :compile-path
 "/Users/kenjin/github/lein-zinc/test-project/target/classes",
 :deploy-repositories
 [["clojars"
   {:password :gpg,
    :username :gpg,
    :url "https://clojars.org/repo/"}]],
 :group "test-project",
 :useZincServer true,
 :license
 {:name "Eclipse Public License",
  :url "http://www.eclipse.org/legal/epl-v10.html"},
 :resource-paths
 ("/Users/kenjin/github/lein-zinc/test-project/dev-resources"
  "/Users/kenjin/github/lein-zinc/test-project/resources"),
 :uberjar-merge-with
...

で、このマップが、Leiningenのプラグインの関数に引数として渡されます。

(defn zinc "lein zinc plugin entry point" 
  [project]
  (let [{:keys [useZincServer zincPort]
         :or {useZincServer false
              zincPort 9999}} project]
  (main/debug "zinc task is invoked")
  (main/debug "zincPort:" zincPort)
  (main/debug "useZincServer:" useZincServer)))

マップバインディングフォームのキーワード:keysを用いることで、使いたいキーワードをマップから抽出して、そのキーワード名がそのまま変数となり、値を格納します。(clojure.core/keysとは違うことに注意!)

$ DEBUG=true lein zinc
Leiningen's classpath: ../src::/usr/local/Cellar/leiningen/2.5.0/libexec/leiningen-2.5.0-standalone.jar
Applying task zinc to []
zinc task is invoked
zincPort: 9999
useZincServer: true

project.cljにキーバリューが指定されていればその値が用いられます。(上記の例ではuseZincServer) 但し、存在していない場合はnilが返されます。デフォルト値を設定したい場合は、キーワード:orを用います。上記の例では、project.cljzincPortが設定されていないので、デフォルト値の9999が用いられています。