다른 컨텍스트에서 로컬 변수와 컨텍스트 문제가 발생했습니다.
fn
평가되지 않은 코드를 저장할 수 있는 특별한 -alternave 를 만들고 싶습니다 . (다음 코드에서 my-fn
)
내 사용 사례에서는이 코드를 변경해야합니다. 나는 이것을 위해 morph
-macro를 사용할 것이지만 이것 없이도 내 문제가 나타납니다.
; Should work like fn, but save the code of args and body
(defmacro my-fn
[args body]
(with-meta (list 'fn args body)
{:args (list 'quote args)
:body (list 'quote body) }))
; in this macro, the predicate should be morphed later.
; Both args and body will be needed.
; To show my problem, i will skip this morphing and return just the body
(defmacro morph
[args body]
body)
이제 몇 가지 예제 데이터를 선택하고 my-fn
. 새 함수를 모핑하고 평가하는 동안 조건 자 내부의 로컬 변수를 확인할 수없는 일이 발생합니다.
; example data for this case
(def people #{{:id "S1" :name "Smith" :status 20 }
{:id "S2" :name "Jones" :status 10 }
{:id "S3" :name "Blake" :status 30 }})
(let [a 20
f (my-fn [t] (<= a (:status t)))] ; pred should be used like fn
(let [pred (eval (list 'fn ; later this second let code comes into a macro or somehting
(:args (meta f))
(list 'morph
(:args (meta f))
(:body (meta f)))))]
(filter pred people))) ; => clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to resolve symbol: a in this context
누군가가 왜 이런 일이 발생하며 어떻게 피할 수 있는지 설명 할 수 있습니까? a
의 정의 대신 상수를 사용 f
하면 모든 것이 잘 작동합니다. 그러나 이것은 내 사용 사례에 도움이되지 않습니다 ...
좋아, 로컬 바인딩에 대한 설명에 감사드립니다. 내 유스 케이스의 경우 로컬 바인딩 사용을 포함하여 my-fn
같은 fn
것을 사용할 수 있다는 것이 정말 중요 합니다.
매크로에서 로컬 바인딩에 액세스하기 위해이 스레드 를 찾았습니다 .
그래서 나는 로컬 환경을 저장하고 위의 모든 로컬 바인딩 (나중 버전에서는 필요한 바인딩 만)과 조건 자 단어를 사용하여 변형 된 술어 주위에 my-fn
배치 let
합니다.
그래서 내 새 버전의 함수와 매크로는 다음과 같습니다.
(defmacro my-fn
[args body]
(with-meta (list 'fn args body)
{:args (list 'quote args)
:body (list 'quote body)
:env (list 'get-env)}))
(defmacro morph
[args body]
body)
; example data for this case
(def people #{{:id "S1" :name "Smith" :status 20 }
{:id "S2" :name "Jones" :status 10 }
{:id "S3" :name "Blake" :status 30 }})
(let[a 20
f (fn [t] (<= a (:status t)))]
(filter f people))
(defmacro get-env
[]
(into {} (for [k (keys &env)]
[(name k) k])))
(let [a 20
f (my-fn [t] (<= a (:status t)))] ; pred should be used like fn
(let [env (get-env)
pred (eval (list 'fn ; later this second let code for comes into a macro or somehting
(:args (meta f))
(list 'let
(reduce (fn[v [x y]] (conj v (read-string x) y)) [] (:env (meta f)))
(list 'morph
(:args (meta f))
(:body (meta f))))))]
(filter pred people))) ; => ({:id "S3", :name "Blake", :status 30} {:id "S1", :name "Smith", :status 20})
고마워!
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다