(defrecord Foo [...]
...
IFn
(invoke [this] (do-this-on-zero-argument-call))
(invoke [this x] (do-when-called-with-x))
(invoke [this x y] (+ x y)))
=> ((Foo.) 33 9)
42
=>
--
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 clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
You could also use reify:(defn make-foo [s](reify clojure.lang.IFn(invoke [this] (str "Hello, " s))))((make-foo "RJ"))"Hello, RJ"I have to admit, though, that I'm unclear on the relative merits of defrecord vs. reify. Anyone want to comment?Cheers,-Michael Nygard
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
Not easily. You may be able to override applyTo to get that to work.
Alternatively, you can work around it by using destructuring and an
extra vector around the args:
(defrecord Foo [a]
clojure.lang.IFn
(invoke [this [& args]] (println (str a args))))
(def yo (Foo. "sam"))
(yo [1 2 3 4])
A bit ugly, but it should work.
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
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...
--