Perhaps I'm being dense but I still fail to see what the issue is here:
(defn setter [sym]
`(defn ~(symbol (str "set-" sym)) [~'x ~'y]
(assoc ~'x ~(keyword (str sym)) ~'y)))
(defn getter [sym]
`(defn ~(symbol (str "get-" sym)) [~'x]
(~(keyword (str sym)) ~'x)))
(defmacro accessors [& syms]
`(do
~@(map getter syms)
~@(map setter syms)))
(accessors x y)
(set-x {} 4) ; -> {:x 4}
(get-x (set-x {} 4)) -> 4
Is this really so hard? I'll also point out that making maps work the way
you propose isn't even particularly ideal because _anything_ in Clojure can
be a key not just keywords.
p.{"first": "Bob", "second": "Smith"} = 5
Makes absolute no sense in, say, Python, but
(assoc some-map {:first "Bob" :second "Smith"} 5)
is perfectly valid in Clojure. How do you propose to reconcile this?
Just asking ;)
On Fri, Apr 24, 2009 at 5:39 PM, Mark Engelberg <[email protected]>wrote:
>
> Laurent, I think we're actually mostly in agreement here, although we
> differ on some of the details.
>
> I agree with the Principle of Uniform Access. One interpretation of
> this principle is that coders should never have a public field, and
> should always use getters and setters, to make the API future proof.
> This is how Java does things (or has it improved in latest versions?),
> but many programmers (including myself) don't like this. So most
> recent languages (C#, Scala) let you start out with public fields, and
> then later, you can create methods which are actually called under the
> covers by the standard assignnment and lookup mechanism in the
> language, disguising these dynamic properties as standard fields. The
> point is, you start out using the simplest thing to express your data
> structure, and then you can convert it effortlessly IF you end up
> needing to.
>
> In Clojure, most new data structures are going to be implemented as a
> map. I am well aware that you could define getters and setters for
> every single field to protect yourself. But I would prefer to start
> with the simplest possible implementation, and be able to grow it
> gracefully if need be. In other words, I want to start out just
> representing my data structure as a map. I want to be able to use the
> wonderfully convenient notations that Clojure allows (e.g.,
> (:numerator rational) to look up the numerator in a structure
> representing a rational number). And then, I want my client code to
> *not break* when my needs grow.
>
> In Clojure, you can do amazing things with maps, making it an ideal
> tool for rapid coding, especially in the initial phase where
> interfaces and design needs change frequently. At the other end of
> the spectrum, you can also code elaborately complex things as Java
> classes, interfaces, and proxies to implement them. But there isn't
> much you can do in between. If you start with a map, and your needs
> grow, you're kind of stuck and need to do a pretty elaborate rewrite.
> It seems to me there's a need for something that works like a map,
> letting you continue to use the standard associative interface such as
> get, assoc, keyword access notation, =, etc., but can handle slightly
> more complex things, perhaps with better hooks for customizing
> equality, or hiding certain parts of the map, or providing a special
> function to be called when using assoc and get with certain keywords
> on a given map.
>
> On Fri, Apr 24, 2009 at 9:46 AM, Laurent PETIT <[email protected]>
> wrote:
> > Why do you say "things kind of break down" ?
> >
> > (:key my-map) is a function call ? Everything is always (almost) a
> > function call in clojure ?
>
> Yes, but as far as I know, it doesn't call anything you can customize.
> I believe it calls get, which you can't hook into without
> reimplementing your data structure as a proxy for the associative
> interface.
>
> >
> > I think an idea could be to have (get) and (set) polymorphic via
> > multimethods (if they aren't already, maybe I don't know), but that
> > would certainly be a performance killer ?
>
> Yes, if all the built-in things were implemented as multimethods, a
> lot of my extensibility/scalability concerns would go away. But they
> aren't (presumably for performance reasons). They are implemented as
> Java interfaces, and you can't easily make a map respond differently
> to these interfaces. You have to custom code your own map-like thing
> via proxy. And equality and hashing are even more difficult to
> customize.
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
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
-~----------~----~----~----~------~----~------~--~---