Construct a List of Maps
First of all I'm a Clojure beginner and sry for my bad English.
Lets say you have a function that is suppossed to return a List of Maps containing various Information (in this example Systeminformation).
I've come up with the following example but it just seems wrong and overcomplicated to me.
My Problem is that 'for [disk (File/listRoots)' already returns a list and I have to merge the 2 Lists in order to get the desired Output, for which must exist a better Solution.
I hope that somebody of you can enlighten me of how to do that in a more 'Clojure way'.
(import
[java.lang Runtime System]
[java.io File])
(defn get-sysinfo []
(let [basic-info (list
{:name "Processor Count:", :value (. (Runtime/getRuntime) availableProcessors)}
{:name "OS Name:", :value (System/getProperty "os.name")}
{:name "OS Arch:", :value (System/getProperty "os.arch")}
{:name "User Name:", :value (System/getProperty "user.name")}
{:name "Java Version:", :value (System/getProperty "java.version")})]
(concat basic-info (for [disk (File/listRoots)]
{:name (str "Disk " (. disk getAbsolutePath)), :value (str "Free Space " (float (/ (. disk getFreeSpace) (* 1024 1024 1024))) " GB")}))))
Thanks in advance
M开发者_开发技巧arkus
You can also use the little list*
helper. It creates a list from the given elements. The last of which is taken as a tail list. So the "merging" happens implicitly.
(defn get-sysinfo
[]
(list*
{:name "Processor Count:" :value (.availableProcessors (Runtime/getRuntime))}
{:name "OS Name:", :value (System/getProperty "os.name")}
{:name "OS Arch:", :value (System/getProperty "os.arch")}
{:name "User Name:", :value (System/getProperty "user.name")}
{:name "Java Version:", :value (System/getProperty "java.version")}
(for [disk (File/listRoots)]
{:name (str "Disk " (.getAbsolutePath disk))
:value (str "Free Space " (float (/ (.getFreeSpace disk)
(* 1024 1024 1024)))
" GB")})))
However, maybe you really want to return a map?
(defn get-sysinfo-map
[]
(into {"Processor Count" (.availableProcessors (Runtime/getRuntime))
"OS Name" (System/getProperty "os.name")
"OS Arch" (System/getProperty "os.arch")
"User Name" (System/getProperty "user.name")
"Java Version" (System/getProperty "java.version")}
(for [disk (File/listRoots)]
[(str "Disk " (.getAbsolutePath disk))
(float (/ (.getFreeSpace disk) (* 1024 1024 1024)))])))
Since you're using (for ...) to transform each element, map seems a more logical choice. You can't really avoid merging two lists since one is "fixed" and the other is generated later from the file listings.
It's also more idiomatic to use (.methodName object) instead of (. object methodName) - though that's purely a style issue.
I'd do it something like:
(defn get-sysinfo []
(concat (list
{:name "Processor Count:", :value (. (Runtime/getRuntime) availableProcessors)}
{:name "OS Name:", :value (System/getProperty "os.name")}
{:name "OS Arch:", :value (System/getProperty "os.arch")}
{:name "User Name:", :value (System/getProperty "user.name")}
{:name "Java Version:", :value (System/getProperty "java.version")})
(map #(hash-map :name (str "Disk " (.getAbsolutePath %)),
:value (str "Free Space "
(float (/ (.getFreeSpace %) (* 1024 1024 1024)))
" GB"))
(File/listRoots))))
精彩评论