Как я могу написать математические функции в Clojure, используя Hiccup и Compojure?

У меня есть отображаемая страница home, которая запрашивает пользовательский ввод в виде векторов целых чисел. Мне нужны эти структуры данных, потому что они хорошо сочетаются с математическими функциями, которые я буду использовать для обработки ввода:

(defn home [& [weights grades error]]
  (html
    ;; ...
   (form-to [:post "/"]
    ;; ...
    (text-area {:rows 15 :cols 30 :placeholder
"[89 78 63]
                    [78 91 60]
                    [87 65 79]
                    ..." } "grades" grades)]
     (submit-button "process"))]))

И кнопка "process" отправляет ввод через функцию defroutes, используя метод POST, который вызывает метод processed, который отображает html, показывая вычисленные результаты ввода. Функция, используемая для расчета окончательного списка оценок, называется process-grades. Я пытаюсь использовать read-string, чтобы изменить входные структуры данных во что-то, что моя функция может обрабатывать, но не может заставить ее работать. Когда я заменяю вызов processed на "TEST", у меня не возникает проблем с отображением текста после нажатия кнопки process:

(defn process-grades 
  "Takes user input from home's form-to function and processes it into the final grades list"
  [weights grades]
(->> grades
     (map (partial percentify-vector weights))
     (mapv #(apply + %))))

(defn processed [weights grades]
  (cond
   (empty? weights)
   (home weights grades "You forgot to add the weights!")
   (empty? grades)
   (home weights grades "You forgot to add the grades!")
  :else
  (do
  (html  
   [:h2 "These are your final grades."]
   [:hr]
   [:p (process-grades (read-string weights)(read-string grades))])))) ;; <- This is not working!


(defroutes grade-routes
           (GET "/" []
                {:status 200
                 :headers {"Content-Type" "text/html"}
                 :body (home)
                 })
           (POST "/" [weights grades] (processed weights grades))
           (ANY "*" []
                (route/not-found (slurp (io/resource "404.html")))))

Я немного изучил тег html form, функцию Clojure read-string и различные способы написания необходимых мне функций. С избытком информации я все еще задаюсь вопросом: каков самый простой, краткий, идиоматический способ сделать это? Должен ли я использовать Clojurescript или я могу использовать Clojure JVM со вкусом ванили здесь?


person kurofune    schedule 27.02.2014    source источник
comment
Я бы рекомендовал использовать здесь clojure.edn/read-string, потому что ваши данные поступают из ненадежного источника (пользовательский ввод). Использование core/read-string может привести к произвольной оценке кода.   -  person Daniel Neal    schedule 27.02.2014
comment
Значит ли это, что я могу добавить функциональность без использования языка сценариев? И допустим, я использую Clojurescript из другого пространства имен, будет ли clojure.edn/read-string работать и в этих функциях? Я действительно новичок во всем этом, поэтому прошу прощения, если мои вопросы наивны.   -  person kurofune    schedule 27.02.2014
comment
Не беспокойтесь - да, я почти уверен, что здесь нет необходимости в языке сценариев. Просто отправьте данные POST на сервер, а затем проанализируйте их с помощью clojure.edn/read-string на сервере. Какую ошибку вы получаете в данный момент?   -  person Daniel Neal    schedule 27.02.2014
comment
Одна вещь, которую я заметил, это то, что ваш образец ввода представляет собой набор векторов [1 2 3] [4 5 6] [7 8 9], что может привести к нежелательным результатам, поскольку read-string читает только один объект из строки.   -  person Daniel Neal    schedule 27.02.2014
comment
Я получаю ошибку 500 от оболочки, которая определена в моих дефрутах, когда я пробую ее без модификации clojure.edn/read-string, и сервер не запускается, когда я использую clojure.edn, бросая java.lang.ClassNotFoundException: clojure.edn в свой терминал . Мне нужно добавить дополнительную зависимость или что-то в этом роде?   -  person kurofune    schedule 27.02.2014
comment
Я уже думал об этом и даже пытался ввести один вектор векторов вручную в область ввода браузера, что является точной формой, которую должны принимать функции. например: [[34,5 45,7 56,4] [71,0 82,7 93,5] [98,0 87 76] [67 78 56]]. Я также поместил это в кавычки и протестировал его с помощью строки чтения в ответе, чтобы убедиться, что он возвращает желаемую структуру.   -  person kurofune    schedule 27.02.2014
comment
давайте продолжим это обсуждение в чате   -  person Daniel Neal    schedule 27.02.2014


Ответы (1)


Вы получаете сообщение об ошибке, потому что (process-grades) возвращает вектор чисел, что означает, что форма ниже

[:p (process-grades (read-string weights) (read-string grades))]

в конечном итоге будет выглядеть следующим образом (после возвращения process-grades):

[:p [4/5 3/2 6/3 ... more numbers]]

Иккинг знает, как обрабатывать html-теги ключевых слов только в начале каждого вектора икоты, поэтому он будет громко жаловаться на это.

В конце концов вам нужно будет красиво отформатировать вывод так, как вы хотите, но на данный момент вы должны иметь возможность запустить его, обернув вызов (process-grades ...) в (apply str), чтобы преобразовать вектор в строку.

person Daniel Neal    schedule 27.02.2014