Interesting -- it's certainly more generic than the solution that I have
worked up. I'd need to add something for the variadic fall-back call.

Thank you!

Francis Avila <[email protected]> writes:

> This is exactly the approach to take: a macro which expands to a defn with 
> all your arities filled out.
>
> Here's a simple approach which might be enough for your problem: it will 
> splice in argument names whenever some marker symbol is encountered, and 
> repeat for the range of arities you want.
>
>
> (defn splice [marker replacement form]
>   (cond
>     (seq? form) (reduce #(if (= marker %2)
>                           (into %1 (reverse replacement))
>                           (conj %1 (splice marker replacement %2)))
>                   () (reverse form))
>     
>     (or (vector? form) (set? form))
>     (reduce #(if (= marker %2)
>               (into %1 replacement)
>               (conj %1 (splice marker replacement %2)))
>       (empty form) form)
>     
>     (map? form)
>     (reduce-kv #(assoc %1 (splice marker replacement %2)
>                           (splice marker replacement %3)) {} form)
>     
>     (= marker form)
>     (throw (ex-info "Cannot splice into a top-level form!" {}))
>     
>     :else form))
>
> (defmacro defvariadic
> ;; Full support for defn options (attr-map, docstring, pre/post conditions)
> ;; an exercise for the reader.
>   [name marker max-arity params & body]
>   (assert (and (symbol? name) (nil? (namespace name))))
>   (assert (and (symbol? marker)))
>   (assert (and (integer? max-arity) (<= 0 max-arity 24)))
>   (assert (vector? params))
>   (let [arg-syms (mapv gensym (subs "abcdefghijklmnopqrstuvwxyz" 0 
> max-arity))
>         params+bodies
>                  (map (fn [arity]
>                         (let [var-params (subvec arg-syms 0 arity)]
>                           (list* (splice marker var-params params)
>                             (splice marker var-params body))))
>                    (range max-arity))]
>     `(defn ~name ~@params+bodies)))
>
>
> This produces output like the following:
>
> (clojure.pprint/pprint (macroexpand-1
>   '(defvariadic default-ontology-dispatch <> 5
>     [f <>]
>     (dispatch f <>))))
>
>
> (clojure.core/defn
>  default-ontology-dispatch
>  ([f] (dispatch f))
>  ([f a23733] (dispatch f a23733))
>  ([f a23733 b23734] (dispatch f a23733 b23734))
>  ([f a23733 b23734 c23735] (dispatch f a23733 b23734 c23735))
>  ([f a23733 b23734 c23735 d23736]
>   (dispatch f a23733 b23734 c23735 d23736)))
>
>
>
>
>
>
> On Thursday, June 4, 2015 at 11:55:23 AM UTC-5, Phillip Lord wrote:
>>
>>
>> I have a number of fairly nasty functions with a form that looks like 
>> this: 
>>
>> (defn default-ontology 
>>   ([f] 
>>      (dispatch f)) 
>>   ([f a] 
>>      (dispatch f a)) 
>>   ([f a b] 
>>      (dispatch f a b)) 
>>   ([f a b c] 
>>      (dispatch f a b c)) 
>>   ([f a b c d] 
>>      (dispatch f a b c d)) 
>>   ([f a b c d e] 
>>      (dispatch f a b c d e)) 
>>   ([f a b c d e fa] 
>>      (dispatch f a b c d e fa)) 
>>   ([f a b c d e fa g] 
>>      (dispatch f a b c d e fa g)) 
>>   ([f a b c d e fa g h] 
>>      (dispatch f a b c d e fa g h)) 
>>   ([f a b c d e fa g h i] 
>>      (dispatch f a b c d e fa g h i)) 
>>   ([f a b c d e fa g h i j] 
>>      (dispatch f a b c d e fa g h i j))) 
>>
>> The reason for all of this is that I need to avoid the use of variadic 
>> function calls for performance reasons -- this function gets called a 
>> lot in my code base, and without this unwinding, I box and unbox 
>> consistantly. 
>>
>> Now, I dislike the code repetition here, and indeed have found already 
>> found one bug in my code where I missed a variable out, something like.... 
>>
>> ([f a b c d] 
>>  (dispatch f a b d)) 
>>
>> which is hard to pick up on. 
>>
>> I can't make the whole thing a macro because I need to pass this as a 
>> first class function. And I can't macro each of the variadic elements 
>> since the I'd need to return two elements at once. 
>>
>> The best I have done up with so far is: 
>>
>> (defn ^:private form-with-arity[n] 
>>   ;; left as an exercise for the reader     
>> ) 
>>
>> (defmacro ^:private m-default-ontology 
>>   `(defn default-ontology 
>>       ~@(map form-with-arity (range 1 10)))) 
>>
>> (m-default-ontology) 
>>
>> Or am I missing something more obvious? 
>>
>> Phil 
>>
>>

-- 
Phillip Lord,                           Phone: +44 (0) 191 208 7827
Lecturer in Bioinformatics,             Email: [email protected]
School of Computing Science,            
http://homepages.cs.ncl.ac.uk/phillip.lord
Room 914 Claremont Tower,               skype: russet_apples
Newcastle University,                   twitter: phillord
NE1 7RU                                 

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to