【问题标题】:Use a get parameter as a function name使用 get 参数作为函数名
【发布时间】:2014-12-31 23:43:20
【问题描述】:

这是我的 clojure-ring 处理程序

(defn handler [req]
  (let [distr (get-in req [:query-params "dist"])]
    (def sortie (describe (eval ((resolve (symbol distr)) 1 3))
                         0.5 0.25 3))
    {:status 200
     :headers {"Content-Type" "text/html"}
     :body (str "<p>" (print-str sortie) "<p>")}
  ))

(def app
  (-> #'handler
    (ring.middleware.stacktrace/wrap-stacktrace)
    (wrap-spy)
    (wrap-params)
    ))

“dist”键映射到一个字符串。

:query-params {"dist" "gaussian-dist"}

我想用它作为函数名。 整个

(eval ((resolve (symbol distr)) 1 3)) 

返回地图

当我用字符串替换 distr 时,它会按需要工作。

=> (eval ((resolve (symbol "gaussian-dist")) 1 3))
{:Distribution :actuarial.distributions/Gaussian, :Parameters {:sigma 3, :mu 1}}

编辑:

这就是我最终解决问题的方式: 再次感谢,我是 Clojure 的初学者

我用宏解决了这个问题

(defmacro get-map [map name]
  `(get ~map ~name))

(defn handler [req]
  (let [distr-name (get-in req [:query-params "dist"])
        distr-map ((get-map distributions-map distr-name) 1 3)
        sortie (describe distr-map 0.5 0.25 3)
        ]

    {:status 200
     :headers {"Content-Type" "text/html"}
     :body (str "<p>" sortie "<p>")}))

【问题讨论】:

  • distr 的值似乎很可能与预期不符,您可以放入 println 或以其他方式检查它并包含输出吗?
  • 不要在函数内部使用 def。 sortie 可以在使用前被另一个请求替换。
  • 这个宏没有做任何你不能用函数做的事情,更简单地说:(defn get-map [map name] (get map name)),或者真的是(def get-map get)

标签: clojure ring


【解决方案1】:

从安全性和可维护性的角度来看,让 Internet 将命名空间中的任何符号作为函数调用似乎有点冒险,所以我的想法是改为:

准备用户应该能够请求的函数的白名单,以从查询参数字符串到函数的映射的形式。

(def distributions {"gaussian-dist" gaussian-dist})

创建一个默认函数,该函数要么发出错误消息,要么只选择一些默认分布。
得到查询时,只需使用getdistributions中查找您需要的函数,以及处理未找到查询字符串情况的默认函数即可。

(let [distr (get-in req [:query-params "dist"])
      sortie ((get distributions distr default-fn) 1 3)]

对于每个请求,defsortie 这样的 var 也有点冒险,因为这会使您面临竞争条件。这就是为什么let 这个名字似乎更自然,除非处理程序比我在这里看到的更多。您还可以使用(def ^:dynamic *sortie*)binding 做您想做的事情,这会将不同线程的绑定相互隔离以防止这种情况发生。

【讨论】:

  • 在请求处理程序中定义符号不仅“有点冒险”,而且完全是错误的。 Vars 是全局可访问的可变状态,没有并发机制。
猜你喜欢
  • 2013-03-31
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-16
相关资源
最近更新 更多