Построить список карт - PullRequest
1 голос
/ 06 июня 2011

Прежде всего, я новичок в Clojure и прошу прощения за мой плохой английский.

Допустим, у вас есть функция, которая, как предполагается, возвращает список карт, содержащих различную информацию (в этом примере - системная информация).

Я придумал следующий пример, но он мне кажется просто неправильным и слишком сложным.

Моя проблема в том, что 'for [disk (File / listRoots)' уже возвращает список, и мне нужно объединить 2 списка, чтобы получить желаемый результат, для которого должно существовать лучшее решение.

Я надеюсь, что кто-то из вас сможет рассказать мне о том, как сделать это более "Clojure способом".

(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")}))))

Заранее спасибо

Маркус

Ответы [ 2 ]

1 голос
/ 06 июня 2011

Вы также можете использовать маленький помощник list*. Создает список из заданных элементов. Последний из которых берется за хвостовой список. Таким образом, «слияние» происходит неявно.

(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")})))

Однако, может быть, вы действительно хотите вернуть карту?

(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)))])))
1 голос
/ 06 июня 2011

Поскольку вы используете (для ...) для преобразования каждого элемента, карта кажется более логичным выбором. Вы не можете избежать объединения двух списков, так как один «исправлен», а другой создается позже из списков файлов.

Также более идиоматично использовать (объект .methodName) вместо (. Object methodName) - хотя это чисто вопрос стиля.

Я бы сделал что-то вроде:

(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))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...