So, for a random project, I found myself using a single protocol
extended to a bunch of record types. I did this using the support
in `defrecord` itself, but what I dislike about it is that the
definitions for each method of the protocol are spread out amongst
multiple sections of code.
What I'd really like to do would be to define an implementation for
many types within a single definition. Conceptually, this is the
same thing you might do in OCaml or other staticly typed languages:
let bar x = match x with
| String y -> ...
| Character y -> ...
So, I came up with this (below), only it doesn't work. I haven't dug deep
yet to figure out why exactly, or if this could even technically be done
without manipulating something in core. (I'm going to assume for now
that I missed something simple, and it could be fixed trivially.)
(defprotocol Foo
(bar [_] "do bar")
(baz [_] "do baz"))
(defmacro defp [proto name arglist & bodies]
(let [pairs (partition 2 bodies)
protocol (resolve proto)
namekw (keyword name)
impls (reduce (fn [accum [t body]]
(let [tm (assoc
(get accum t {})
namekw `(fn ~arglist ~body))]
(assoc accum t tm)))
(get :impls protocol {})
pairs)]
`(def ~proto (assoc (var-get ~protocol) :impls ~impls))))
(defp Foo bar [x]
String (concat x x)
Character (list x x))
(defp Foo baz [x]
String (rest (seq x))
Character nil)
So, is there a technical reason why this is a bad idea, other than
"the interface might change in the future"? And, If people are actually
into this idea, what adjustments should be made to the syntax?
Thanks in advance,
Andrew
That certainly works, but it's really not much different than:
(defrecord Bar [x y]
Foo
(bar [_] ...)
(baz [_] ...)
which is what I'm trying to avoid.
It seems to me that the only reason that specifying the entire
implementation together is to avoid situations where the
implementation is not completely defined.
See, I'm less concerned about implementing the Protocol than I am
about creating "functions" that are dispatched by type, and since they
have to have the same argument list, I see no reason why that
boilerplate can't be eliminated.
Perhaps one solution for me is to write a macro that constructs a
protocol (and extends it to types) out of the definitions provided..
sort of a hybrid of extend-protocol and defp from before.
(defwhatever Foo
(bar [_]
String (body)
Character (body))
(baz [_]
String (body)
Character (body)))
Which gets me to where I ultimately want to be (methods defined
together per type extended too), but not quite what I'm really looking
for.
> 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
Now it sounds like you might want a plain old multimethod.
It'd be more easily done with multimethods, sure, but since they all
implement both methods, there's no reason to not use protocols. See
the dilemma?
> --
(defprotocol Foo
(bar [_] "do bar")
(baz [_] "do baz"))
(defmacro defp [name arglist proto & bodies]
(let [pairs (partition 2 bodies)
protocol (resolve proto)
namekw (keyword name)
impls (reduce (fn [accum [t body]]
(let [tm (assoc
(get accum t {})
namekw `(fn ~arglist ~body))]
(assoc accum t tm)))
(get :impls protocol {})
pairs)]
`(clojure.core/-reset-methods (alter-var-root ~protocol assoc
:impls ~impls))))
(defp bar [x] Foo
String (concat x x)
Character (list x x))
(defp baz [x] Foo
String (rest (seq x))
Character nil)
(and changing up the interface to it a bit) this seems to work.
Though, it doesn't return (satisfies? Foo String) correctly, but, I'll
either figure that out later, or ultimately not care.
Am 07.02.2011 um 23:53 schrieb Andrew Gwozdziewycz:
> Though, it doesn't return (satisfies? Foo String) correctly, but, I'll
> either figure that out later, or ultimately not care.
satisfies? is about instances.
Sincerely
Meikel
Ooh! Good point. Thanks!
On Feb 7, 2011 6:56 PM, "Meikel Brandmeyer" <m...@kotka.de> wrote:
Hi,
Am 07.02.2011 um 23:53 schrieb Andrew Gwozdziewycz:
> Though, it doesn't return (satisfies? Foo String) correctly, but, I'll
> either figure that out l...
satisfies? is about instances.
Sincerely
Meikel
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post t...