> Is there any way of identifying an instance of it. I know > about multimethods and using that with something like > :type as a struct field.
> I am just wondering if there is something like sclass > that would be a 'class' equivalent for structure
> (sclass (struct mystruct)) => mystruct
> (class (struct mystruct)) gives clojure.lang.PersistentStructMap > as expected.
You would need access to the "def" attribute of the PersistentStructMap, to test that the map's def is identical to the def in your test-function (or to compare the set of keyslots in your map to the keyslots in the def, which would be a looser "duck typing" comparison but might be more practical).
But scanning the Java source for PersistentStructMap, it looks like the "def" attribute is not public and so cannot be read from Clojure. I think this ought to be changed, and you might consider writing a patch to add a couple new methods:
PersistentMap.getDef, returning a Def Def.getKeyslots, returning an IPersistentMap
Or alternately, just make both of these attributes public, but I suspect that Rich might reject such a patch.
From there you could write the comparison function in Clojure (or add an instanceOf method to the Def class, that could do your testing for you).
It doesn't look like it. It appears that although the StructMap keeps a reference to the Def, there's no way to get it back out. Even if there were, I'm not sure how you'd get back to the name given to the Def -- in fact, there could be many (or no) names. Here's an anonymous struct:
But this all seems a little wrong. I think structs are meant to be just a little performance (memory) improvement over a regular hashmap. It seems like meta-data would be a better fit, but I'm not quite sure how to use it:
On Wed, Aug 20, 2008 at 9:46 AM, Chouser <chou...@gmail.com> wrote:
> On Wed, Aug 20, 2008 at 7:11 AM, Parth Malwankar > <parth.malwan...@gmail.com> wrote:
>> (sclass (struct mystruct)) => mystruct
> It doesn't look like it. It appears that although the StructMap keeps > a reference to the Def, there's no way to get it back out. Even if > there were, I'm not sure how you'd get back to the name given to the > Def -- in fact, there could be many (or no) names.
Right, but you could have a predicate, (mystruct?), that compared an instance's Def for identity with mystruct's Def. Again, though, I wonder if duck-typing would make more sense here (comparing the set of keyslots, rather than comparing Defs for identity).
I see that Parth was asking for a type-of-struct function, and in my response I was thinking in terms of a predicate, which isn't the same thing. Though in practice a predicate often suffices.
> On Wed, Aug 20, 2008 at 9:46 AM, Chouser <chou...@gmail.com> wrote:
> > On Wed, Aug 20, 2008 at 7:11 AM, Parth Malwankar
> > <parth.malwan...@gmail.com> wrote:
> >> (sclass (struct mystruct)) => mystruct
> > It doesn't look like it. It appears that although the StructMap keeps
> > a reference to the Def, there's no way to get it back out. Even if
> > there were, I'm not sure how you'd get back to the name given to the
> > Def -- in fact, there could be many (or no) names.
> Right, but you could have a predicate, (mystruct?), that compared an
> instance's Def for identity with mystruct's Def. Again, though, I
> wonder if duck-typing would make more sense here (comparing the set of
> keyslots, rather than comparing Defs for identity).
> I see that Parth was asking for a type-of-struct function, and in my
> response I was thinking in terms of a predicate, which isn't the same
> thing. Though in practice a predicate often suffices.
> Graham
Don't know if this is what you were looking for but you can tack on
any metadata you like to a struct and check that for your "type".
That's what I do when I want polymorphism. With that solution you
don't need to have the type intrude on the actual data in the struct
instance.
Example:
(defstruct happy-struct :x :y)
(defn make-happy-struct
"Creates a new happy-struct instance."
[x y]
(with-meta (struct happy-struct x y) {:type :happy}))
> On Aug 20, 4:58 pm, "Graham Fawcett" <graham.fawc...@gmail.com> wrote:
> > On Wed, Aug 20, 2008 at 9:46 AM, Chouser <chou...@gmail.com> wrote:
> > > On Wed, Aug 20, 2008 at 7:11 AM, Parth Malwankar
> > > <parth.malwan...@gmail.com> wrote:
> > >> (sclass (struct mystruct)) => mystruct
> > > It doesn't look like it. It appears that although the StructMap keeps
> > > a reference to the Def, there's no way to get it back out. Even if
> > > there were, I'm not sure how you'd get back to the name given to the
> > > Def -- in fact, there could be many (or no) names.
> > Right, but you could have a predicate, (mystruct?), that compared an
> > instance's Def for identity with mystruct's Def. Again, though, I
> > wonder if duck-typing would make more sense here (comparing the set of
> > keyslots, rather than comparing Defs for identity).
> > I see that Parth was asking for a type-of-struct function, and in my
> > response I was thinking in terms of a predicate, which isn't the same
> > thing. Though in practice a predicate often suffices.
> > Graham
> Don't know if this is what you were looking for but you can tack on
> any metadata you like to a struct and check that for your "type".
> That's what I do when I want polymorphism. With that solution you
> don't need to have the type intrude on the actual data in the struct
> instance.
> Example:
> (defstruct happy-struct :x :y)
> (defn make-happy-struct
> "Creates a new happy-struct instance."
> [x y]
> (with-meta (struct happy-struct x y) {:type :happy}))
> (defmethod happy-func :happy
> [instance z]
> (println "And the result is:" (+ (:x instance) (:y instance) z)))
> (def inst (make-happy-struct 10 20))
> ^inst
> => {:type :happy}
> (happy-func inst 30)
> => And the result is: 60
> /mac
Just to clarify myself in case you were just looking for type info,
you can ignore most of what I wrote with defmulti and that stuff. Just
look at with-meta and the dispatch function, which picks out the value
of the :type entry in the metadata. (:type ^instance)
On Wed, Aug 20, 2008 at 11:23 AM, mac <markus.gustavs...@gmail.com> wrote: > On Aug 20, 4:58 pm, "Graham Fawcett" <graham.fawc...@gmail.com> wrote: >> Right, but you could have a predicate, (mystruct?), that compared an >> instance's Def for identity with mystruct's Def. Again, though, I >> wonder if duck-typing would make more sense here (comparing the set of >> keyslots, rather than comparing Defs for identity).
> Don't know if this is what you were looking for but you can tack on > any metadata you like to a struct and check that for your "type". > That's what I do when I want polymorphism. With that solution you > don't need to have the type intrude on the actual data in the struct > instance.
Hi mac,
Sure, I can see that working. But I also see the benefit of exploiting the (currently-hidden) metadata inside a struct Def, namely its set of keyslots, or its identity. Rather than having to tack on extra metadata (adding a designer burden) we could use the Def's own properties for dispatch.
E.g., If we could access the keyslots of a Def, I could write a multimethod that dispatches on any struct-map that has both :label and :coordinates attributes, so that I could plot it on a visual map (duck-typing in all its glory: if it quacks like a plot-point, we can use it as a plot-point) without the struct-map having to be rigged with metadata at some prior stage.
Dispatch is just one case, as you mentioned in your second message, but similarly the keyslot map could be used in other cases too (e.g. writing a (plot-point?) predicate that tested for {:label :coordinates} as a subset).
Of course, "real" duck-typing would be instance based -- I would ask an instance if it had {:label :coordinates} values, not inspect its def/type. Still I suspect there is a case for the def/type inspection as well.
The more I think about it, though, I suspect that instance-testing makes the most sense in most cases, and struct-map types aren't really types in any meaningful way. How's that for circular reasoning! :-)
> Of course, "real" duck-typing would be instance based -- I would ask
> an instance if it had {:label :coordinates} values, not inspect its
> def/type. Still I suspect there is a case for the def/type inspection
> as well.
> The more I think about it, though, I suspect that instance-testing
> makes the most sense in most cases, and struct-map types aren't really
> types in any meaningful way. How's that for circular reasoning! :-)
I was going to write some counter argument here but I sort of agree
with you so I guess I got nothing.
The case for being able to check the Def of a structmap instance I
think would be what you already described; to check the type without
using metadata. But I don't think exposing the Def would be considered
pretty since the structs are just supposed to be slightly more
efficient hashmaps right? But what do I know, I'm a total Lisp/Clojure
noob ;)
Anyway, I guess I would do duck typing the way you described it with
the instances, by checking for non-nil returns on the relevant keys.
Thanks for that idea by the way, hadn't occurred to me before.
Although you would have to be careful with that. If there are two
different maps that have the same keys but they contain different
types of values you could get in trouble with such a dispatch.
Requires using quite specific key names - or checking the type of the
values too if the values exist ;)
/mac
On Aug 20, 6:33 pm, "Graham Fawcett" <graham.fawc...@gmail.com> wrote:
> On Wed, Aug 20, 2008 at 11:23 AM, mac <markus.gustavs...@gmail.com> wrote:
> > On Aug 20, 4:58 pm, "Graham Fawcett" <graham.fawc...@gmail.com> wrote:
> >> Right, but you could have a predicate, (mystruct?), that compared an
> >> instance's Def for identity with mystruct's Def. Again, though, I
> >> wonder if duck-typing would make more sense here (comparing the set of
> >> keyslots, rather than comparing Defs for identity).
> > Don't know if this is what you were looking for but you can tack on
> > any metadata you like to a struct and check that for your "type".
> > That's what I do when I want polymorphism. With that solution you
> > don't need to have the type intrude on the actual data in the struct
> > instance.
> Hi mac,
> Sure, I can see that working. But I also see the benefit of exploiting
> the (currently-hidden) metadata inside a struct Def, namely its set of
> keyslots, or its identity. Rather than having to tack on extra
> metadata (adding a designer burden) we could use the Def's own
> properties for dispatch.
> E.g., If we could access the keyslots of a Def, I could write a
> multimethod that dispatches on any struct-map that has both :label and
> :coordinates attributes, so that I could plot it on a visual map
> (duck-typing in all its glory: if it quacks like a plot-point, we can
> use it as a plot-point) without the struct-map having to be rigged
> with metadata at some prior stage.
> Dispatch is just one case, as you mentioned in your second message,
> but similarly the keyslot map could be used in other cases too (e.g.
> writing a (plot-point?) predicate that tested for {:label
> :coordinates} as a subset).
> Of course, "real" duck-typing would be instance based -- I would ask
> an instance if it had {:label :coordinates} values, not inspect its
> def/type. Still I suspect there is a case for the def/type inspection
> as well.
> The more I think about it, though, I suspect that instance-testing
> makes the most sense in most cases, and struct-map types aren't really
> types in any meaningful way. How's that for circular reasoning! :-)
> Circularly yours,
> Graham
> > Example:
> > (defstruct happy-struct :x :y)
> > (defn make-happy-struct
> > "Creates a new happy-struct instance."
> > [x y]
> > (with-meta (struct happy-struct x y) {:type :happy}))
On Aug 20, 9:33 pm, "Graham Fawcett" <graham.fawc...@gmail.com> wrote:
> On Wed, Aug 20, 2008 at 11:23 AM, mac <markus.gustavs...@gmail.com> wrote:
> > On Aug 20, 4:58 pm, "Graham Fawcett" <graham.fawc...@gmail.com> wrote:
> >> Right, but you could have a predicate, (mystruct?), that compared an
> >> instance's Def for identity with mystruct's Def. Again, though, I
> >> wonder if duck-typing would make more sense here (comparing the set of
> >> keyslots, rather than comparing Defs for identity).
> > Don't know if this is what you were looking for but you can tack on
> > any metadata you like to a struct and check that for your "type".
> > That's what I do when I want polymorphism. With that solution you
> > don't need to have the type intrude on the actual data in the struct
> > instance.
Thanks mac. This example using meta data was very helpful.
> Hi mac,
> Sure, I can see that working. But I also see the benefit of exploiting
> the (currently-hidden) metadata inside a struct Def, namely its set of
> keyslots, or its identity. Rather than having to tack on extra
> metadata (adding a designer burden) we could use the Def's own
> properties for dispatch.
Yes. If we could use properties from def that would be really nice
and would probably make the code cleaner.
> E.g., If we could access the keyslots of a Def, I could write a
> multimethod that dispatches on any struct-map that has both :label and
> :coordinates attributes, so that I could plot it on a visual map
> (duck-typing in all its glory: if it quacks like a plot-point, we can
> use it as a plot-point) without the struct-map having to be rigged
> with metadata at some prior stage.
> Dispatch is just one case, as you mentioned in your second message,
> but similarly the keyslot map could be used in other cases too (e.g.
> writing a (plot-point?) predicate that tested for {:label
> :coordinates} as a subset).
> Of course, "real" duck-typing would be instance based -- I would ask
> an instance if it had {:label :coordinates} values, not inspect its
> def/type. Still I suspect there is a case for the def/type inspection
> as well.
> The more I think about it, though, I suspect that instance-testing
> makes the most sense in most cases, and struct-map types aren't really
> types in any meaningful way. How's that for circular reasoning! :-)
> Circularly yours,
> Graham
> > Example:
> > (defstruct happy-struct :x :y)
> > (defn make-happy-struct
> > "Creates a new happy-struct instance."
> > [x y]
> > (with-meta (struct happy-struct x y) {:type :happy}))
> It doesn't look like it. It appears that although the StructMap keeps
> a reference to the Def, there's no way to get it back out. Even if
> there were, I'm not sure how you'd get back to the name given to the
> Def -- in fact, there could be many (or no) names. Here's an
> anonymous struct:
> But this all seems a little wrong. I think structs are meant to be
> just a little performance (memory) improvement over a regular hashmap.
> It seems like meta-data would be a better fit, but I'm not quite sure
> how to use it: