On Sat, Jun 18, 2011 at 10:47 AM, David Nolen <dnolen.li...@gmail.com> wrote:
> On Sat, Jun 18, 2011 at 4:44 AM, Sam Aaron <samaa...@gmail.com> wrote:
>>
>> Is it possible to use this approach to create a callable record which can
>> take a variable number of arguments?
>>
>> I can't get the following to work:
>>
>> (defrecord Foo [a]
>>  clojure.lang.IFn
>>  (invoke [this & args] (println (str a args))))
>>
>> (def yo (Foo. "sam"))
>>
>> (yo 1 2 3 4) ;=>
>> sc-one.Foo.invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
>>   [Thrown class java.lang.AbstractMethodError]
>>
>> Sam
>
> defrecord/type methods don't support rest args.

Not without some hoop jumping, anyway, but ...

=> (defn my-var-arg-fn [& args] (apply str args))
#'user/my-var-arg-fn
=> (defrecord Foo []
     clojure.lang.IFn
     (invoke [this] (my-var-arg-fn))
     (invoke [this o1] (my-var-arg-fn o1))
     (invoke [this o1 o2] (my-var-arg-fn o1 o2))
     (applyTo [this, arglist]
       (clojure.lang.AFn/applyToHelper my-var-arg-fn arglist)))
user.Foo
=> ((Foo.) "hello" "world")
"helloworld"
=> (apply (Foo.) "hello" "world")
"helloworld"

To really make it work you unfortunately need about 18 more (invoke
...) methods, each with one additional parameter, which is annoying. A
macro could be written to simplify the job. That's for making the
records themselves be functions that accept varargs. To make a random
method do so you'd need to overload it, similarly to the multiple
versions of invoke above, for each arity, or better yet you'd write a
helper function:

(defrecord Foo
  SomeProto
  (my-meth-impl [this [& args]] ...))

(defn my-meth [some-foo & args]
  (my-meth-impl some-foo args))

which just passes the arg seq in as a single, second seq argument to
the record's actual method, which destructures its second argument...

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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

Reply via email to