Clojure использование (для) с икота и нуар
Я использую clojure и сбой (с нуара), и у меня есть этот код:
(defn dataframe [id]
(db/db-to-data id))
(defpartial drop-downs [nms]
(for [nm (keys nms)] (drop-down nm (get nms nm))[:br])
(submit-button "Refresh")
)
(defpage "/dataset/table/:id" {:keys [id]}
(common/layout
(form-to [:post (format "/dataset/table/%s" id)]
(drop-downs {"alessio" [:col0], "test" [:col1]})
)
(html-table (dataframe id))))
Моя проблема с:
(for [nm (keys nms)] (drop-down nm (get nms nm))[:br])
Я хочу иметь множественный выбор в моей форме. Строка выше делает это, но по какой-то причине не учитывает [:br], поэтому не ломает строки. Однако, если я сделаю это:
(form-to [:post (format "/dataset/table/%s" id)]
(drop-down "Test1" "1")[:br]
(drop-down "Test2" "2")[:br]
)
Тег [: br] работает. Я полагаю, что это связано с тем, как работает макрос (for), но я не мог понять причину и как это исправить.
РЕДАКТИРОВАТЬ
Как и советовали, я отказался от использования для. Финальный результат ниже (который является ответом Joost с небольшим модом):
(mapcat #(vector (drop-down % (nms %)) [:br]) (keys nms))
3 ответа
Этот код даже не компилируется; for
принимает ровно два аргумента
Если вы хотите поместить два элемента одновременно в последовательности, возвращаемой for
поместите их в вектор и распакуйте позже.
Хотя лично я предпочитаю mapcat для этих ситуаций. Что-то вроде:
(into (form-to [:post (format "/dataset/table/%s" id)])
(mapcat #(vector (drop-down % (nms %)) [:br]) nms))
Я собрал немного чего-то, что не использует Noir или икоту, но, возможно, поможет вам в лучшем направлении. Он использует mapcat вместо для:
(let [nms {"alessio" [:col0], "test" [:col1]}]
(mapcat
(fn [mapentry] [[:dropdown (first mapentry) (second mapentry)] [:br]]) nms))
;;=> ([:dropdown "alessio" [:col0]] [:br] [:dropdown "test" [:col1]] [:br])
Икотация автоматически "разворачивает" seqs/lists (а не векторы!) Для вас, так что вы можете написать это так:
(for [[k v] nms]
(list (drop-down k v)
[:br])))