함수 객체 나 이름이 주어지면 어떻게 그 객체를 결정할 수 있습니까? (arity func-name)
과 같은 것입니다. 인수에 대응이 Clojure의Clojure : 런타임시 함수의 장점을 찾는 방법은 무엇입니까?
답변
함수의 인수에 대응이 VAR의 메타 데이터에 저장되어 꽤 중심이기 때문에
내가하는 방법이 있기를 바랍니다.
(:arglists (meta #'str))
;([] [x] [x & ys])
이 함수이었다 defn
하거나 또는 명시 적으로 제공된 :arglists
메타 데이터를 사용하여 정의하는 것이 필요하다.
user=> (defn test-func
([p1] "Arity was 1.")
([p1 p2] "Arity was 2.")
([p1 p2 & more-args] (str "Arity was " (+ 2 (count more-args)))))
#'user/test-func
user=> (test-func 1)
"Arity was 1."
user=> (test-func 1 2)
"Arity was 2."
user=> (test-func 1 2 3)
"Arity was 3"
user=> (test-func 1 2 3 4)
"Arity was 4"
user=> (test-func 1 2 3 4 5) ;...
"Arity was 5"
나는 그 기능을 알기 위해 * 함수를 * 실행하고 싶지 않습니다. 그리고이 기능 코드를 변경하고 싶지 않습니다. – GabiMe
음흉 반사 :
(defn arg-count [f]
(let [m (first (.getDeclaredMethods (class f)))
p (.getParameterTypes m)]
(alength p)))
또는 :
(defn arg-count [f]
{:pre [(instance? clojure.lang.AFunction f)]}
(-> f class .getDeclaredMethods first .getParameterTypes alength))
매크로에서 작동하지 않습니다 – GabiMe
하지만 익명 함수에서 작동합니다. +1 –
이것은 익명 함수에 대한 유일한 옵션 인 것 같지만 처음 선언 된 메서드가 invoke 메서드라는 가정이 마음에 들지 않습니다. 내가 대신 '(첫 번째 (필터 # (= "호출"(.getName %)) (.getDeclaredMethods (클래스 f))))''(첫 번째 (.getDeclaredMethods (클래스 f) –
건물 @ whocaresanyway의 솔루션에 :
(defn provided
[cond fun x]
(if cond
(fun x)
x))
(defn append
[xs x]
(conj (vec xs) x))
(defn arity-of-method
[method]
(->> method .getParameterTypes alength))
(defn arities
[fun]
(let [all-declared-methods (.getDeclaredMethods (class fun))
methods-named (fn [name]
(filter #(= (.getName %) name) all-declared-methods))
methods-named-invoke (methods-named "invoke")
methods-named-do-invoke (methods-named "doInvoke")
is-rest-fn (seq methods-named-do-invoke)]
(->> methods-named-invoke
(map arity-of-method)
sort
(provided is-rest-fn
(fn [v] (append v :rest))))))
인수에 대응 문제에서 필자의 다른 솔루션 구축 :
(10)는 사실 또한 매크로에서 작동 :
(defn arg-count [f]
(let [m (first (.getDeclaredMethods (class f)))
p (.getParameterTypes m)]
(alength p)))
(defmacro my-macro [])
(arg-count @#'my-macro)
; 2
왜 2? 모든 매크로에는 두 개의 암시적인 인수 &form
과 &env
이 각각 있기 때문입니다.
내 심장이 피었습니다 (모든 경우 포함).
(defn arity
"Returns the maximum arity of:
- anonymous functions like `#()` and `(fn [])`.
- defined functions like `map` or `+`.
- macros, by passing a var like `#'->`.
Returns `:variadic` if the function/macro is variadic."
[f]
(let [func (if (var? f) @f f)
methods (->> func class .getDeclaredMethods
(map #(vector (.getName %)
(count (.getParameterTypes %)))))
var-args? (some #(-> % first #{"getRequiredArity"})
methods)]
(if var-args?
:variadic
(let [max-arity (->> methods
(filter (comp #{"invoke"} first))
(sort-by second)
last
second)]
(if (and (var? f) (-> f meta :macro))
(- max-arity 2) ;; substract implicit &form and &env arguments
max-arity)))))
(use 'clojure.test)
(defmacro m ([a]) ([a b]))
(defmacro mx [])
(deftest test-arity
(testing "with an anonymous #(… %1) function"
(is (= 1 (arity #(+ % 32))))
(is (= 1 (arity #(+ %1 32))))
(is (= 2 (arity #(+ %1 %2))))
(is (= 13 (arity #(+ %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13))))
(is (= :variadic (arity #(apply + %&))))
(is (= :variadic (arity #(apply + % %&)))))
(testing "with an anonymous (fn [] …) function"
(testing "single body"
(is (= 0 (arity (fn []))))
(is (= 1 (arity (fn [a]))))
(is (= 2 (arity (fn [a b]))))
(is (= 20 (arity (fn [a b c d e f g h i j k l m n o p q r s t]))))
(is (= :variadic (arity (fn [a b & more])))))
(testing "multiple bodies"
(is (= 0 (arity (fn ([])))))
(is (= 1 (arity (fn ([a])))))
(is (= 2 (arity (fn ([a]) ([a b])))))
(is (= :variadic (arity (fn ([a]) ([a b & c])))))))
(testing "with a defined function"
(is (= :variadic (arity map)))
(is (= :variadic (arity +)))
(is (= 1 (arity inc))))
(testing "with a var to a macro"
(is (= :variadic (arity #'->)))
(is (= 2 (arity #'m)))
(is (= 0 (arity #'mx)))))
(run-tests)
- 1. Clojure 함수의 순환 복잡도를 계산하는 방법은 무엇입니까?
- 2. Clojure 함수의 문제점
- 3. 메서드 또는 함수의 호출자를 찾는 방법은 무엇입니까?
- 4. 파이썬의 다른 함수에서 특정 함수의 인수의 기본값을 찾는 방법은 무엇입니까?
- 5. 이 경우 PHP에서 함수의 구현 위치를 찾는 방법은 무엇입니까?
- 6. Clojure : 함수의 메타 데이터를 얻는 방법?
- 7. 런타임시 '합계'조건을 변경하는 방법은 무엇입니까?
- 8. Clojure : 'trie'를 생성하는 방법은 무엇입니까?
- 9. 런타임시 route를 제거하는 방법은 무엇입니까?
- 10. 런타임시 DataTemplate을 만드는 방법은 무엇입니까?
- 11. 런타임시 CurrentCulture를 변경하는 방법은 무엇입니까?
- 12. 런타임시 DLL을 참조하는 방법은 무엇입니까?
- 13. 런타임시 jre를 선택하는 방법은 무엇입니까?
- 14. 런타임시 bitmapfield를 추가하는 방법은 무엇입니까?
- 15. 런타임시 패키지를 만드는 방법은 무엇입니까?
- 16. 런타임시 로더가 라이브러리를 찾는 방법에 대한 질문입니다.
- 17. 가상 함수의 정렬 방법은 무엇입니까?
- 18. Xpath를 찾는 방법은 무엇입니까?
- 19. 내년을 찾는 방법은 무엇입니까?
- 20. userclick을 찾는 방법은 무엇입니까?
- 21. d.android.com에서 찾는 방법은 무엇입니까?
- 22. clojure-clr을 사용하여 InternetExplorer를 자동화하는 방법은 무엇입니까?
- 23. 로그인 Clojure
- 24. 숫자의 sqrt를 찾는 재귀 함수의 문제점
- 25. actionscript2에서 호출하는 함수의 이름을 찾는 방법이 있습니까?
- 26. 런타임시 init 매개 변수를 변경하는 방법은 무엇입니까?
- 27. 런타임시 MEF 플러그인을 제거하는 방법은 무엇입니까?
- 28. 런타임시 LinearLayout의 크기를 변경하는 방법은 무엇입니까?
- 29. 런타임시 이진 이미지 아키텍처를 결정하는 방법은 무엇입니까?
- 30. 런타임시 Silverlight 템플릿을 수정하는 방법은 무엇입니까?
최고. 고마워요. – GabiMe
참고 : 이것은 실제로 defn으로 정의 된 함수에서만 작동합니다. fn 또는 #()로 정의 된 익명의 함수에는 작동하지 않습니다. – kotarak
필자가 볼 수있는 한, 모든 내장 함수에서도 작동합니다. 예를 들어 (: arglists (meta # '+)) 또는 (: arglists (meta #'println)) – GabiMe