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 <mark.engelb...@gmail.com>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 <laurent.pe...@gmail.com>
> 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 clojure@googlegroups.com
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