2014-12-31 2 views
2

으로 GET 매개 변수를 사용하여이 내 Clojure의 링 핸들러는 함수 이름

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

함수 이름으로 사용하고 싶습니다. 내가 문자열이 DISTR를 교체 할 때 전체

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

원하는대로 작동,지도를

를 반환합니다.

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

'distr '의 값이 예상 한 것과 같지 않은 것 같습니다. println을 넣거나 검사하고 출력을 포함 할 수 있습니까? –

+0

def 내부 함수를 사용하지 마십시오. 'sortie '는 사용하기 전에 다른 요청으로 대체 될 수 있습니다. – noisesmith

+0

이 매크로는 함수로는 할 수없는 일을하지 않고,'(defn get-map [map name] (get map name))'또는'(get get-map get) '. – amalloy

답변

3

인터넷에서 모든 기호를 호출하게하는 보안 및 유지 관리의 관점에서 위험한 제안 인 것 같습니다. 귀하의 네임 스페이스에 함수로, 그래서 내 생각은 대신 뭔가를 할 것입니다 :

사용자가 쿼리 매개 변수 문자열에서 기능에 매핑의 형태로 요청할 수 있어야합니다 기능의 화이트리스트를 준비합니다.

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

오류 메시지를 표시하거나 일부 기본 배포를 선택하는 기본 기능을 만듭니다.
쿼리를 얻었 으면 distributions에 필요한 함수를 찾아 get을 사용하고 쿼리 문자열이없는 대소 문자를 처리하는 기본 함수를 찾습니다.

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

sortie 모든 요청과 같은 VAR, 즉 조건을 경주 할을 열어으로도 def에 좀 위험 해. 그렇기 때문에 핸들러가 아니라면 let이라는 이름이 더 자연스러워 보입니다. (def ^:dynamic *sortie*)binding을 사용하여 원하는 작업을 수행 할 수도 있습니다. 이는 서로 다른 스레드의 바인딩을 차단하여이를 방지합니다.

+1

요청 처리기에서 심볼을 정의하는 것은 "다소 위험한"것은 아니며 단지 잘못되었습니다. Vars는 동시성 메커니즘이없는 전역 적으로 액세스 가능한 변경할 수있는 상태입니다. – noisesmith