Hi! Il giorno mercoledì 19 agosto 2009 21:16:35 UTC+2, John Harrop ha scritto: > > On Wed, Aug 19, 2009 at 10:03 AM, Achim Passen <achim....@gmail.com > <javascript:>> wrote: > >> Beware! This snippet relies on unexposed details of clojure's current >> implementation. It might stop working tomorrow, so it's definitely not >> intended for production use, but it might help with debbuging/exploring. > > > Meanwhile, for declared functions this works: > > (map #(if (contains? (set %) '&) [:more (- (count %) 2)] (count %)) > (:arglists ^#'foo)) > > giving results like: > > (0 2 5 [:more 7]) > > (in this case for (defn foo ([] nil) ([glorb fuzzle] nil) ([x y z w u] x) > ([a b c d e f g & more] more))) > > Add this: > > (defn accepts-arity [arities arity] > (or > (contains? (set arities) arity) > (and (vector? (last arities)) (>= arity (second (last arities)))))) > > and you can check if the function accepts a particular arity. (This > expects "arities" in the format output by my map expression. In particular, > a list of numerical arities and possibly a [:more n] entry, which must be a > vector and must be the last item in the list if present, and n must be the > number of required parameters for the "& more" overload.) > > Wrap it all up with two macros: > > (defmacro fn-arities [fn-name] > `(map (fn [x#] (if (contains? (set x#) '&) [:more (- (count x#) 2)] > (count x#))) (:arglists ^#'~fn-name))) > > (defmacro fn-accepts-arity [fn-name arity] > `(accepts-arity (fn-arities ~fn-name) ~arity)) > > user=> (fn-accepts-arity foo 8) > true > user=> (fn-accepts-arity foo 6) > false > user=> (fn-accepts-arity reduce 2) > true > user=> (fn-accepts-arity reduce 3) > true > user=> (fn-accepts-arity reduce 4) > false > user=> (fn-arities map) > (2 3 4 [:more 4]) > > Works for macros, too: > > user=> (fn-arities fn-arities) > (1) > user=> (fn-arities fn-accepts-arity) > (2) > > But, as noted, only works with a name of a declared fn or macro: > > user=> (fn-arities #(+ 3 %)) > #<CompilerException java.lang.ClassCastException: clojure.lang.Cons cannot > be cast to clojure.lang.Symbol (NO_SOURCE_FILE:110)> > > (One thing odd about that: > > user=> (class '#(+ 3 %)) > clojure.lang.PersistentList > > not Cons. Hmm.) > > It also doesn't work with local, named functions, either using let or > using letfn, even if (fn name [args] body) is used and not (fn [args] body): > > user=> (let [x (fn [a] (+ 3 a))] (fn-arities x)) > #<CompilerException java.lang.Exception: Unable to resolve var: x in this > context (NO_SOURCE_FILE:117)> > user=> (let [x (fn x [a] (+ 3 a))] (fn-arities x)) > #<CompilerException java.lang.Exception: Unable to resolve var: x in this > context (NO_SOURCE_FILE:118)> > user=> (letfn [(x [a] (+ 3 a))] (fn-arities x)) > #<CompilerException java.lang.Exception: Unable to resolve var: x in this > context (NO_SOURCE_FILE:119)> > > It's a *very* old thread, but is there any news about this? I mean, is there a way to find the list of accepted arities of an anonymous function, without trying them all and catching the exception?
Thanks! -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.