Hello,

Maybe you should consider creating a single function with 2 arities:
with one argument, it's the getter, with two arguments, it's the
setter (that returns the new type) !


(prop-foo obj) ; --> returns the property prop-foo
(prop-foo obj newval) ; --> returns a new version of obj with prop-foo
property set to newval

Terse and uniform :-)

?



2009/4/26 David Nolen <dnolen.li...@gmail.com>:
> You're right. The following includes code for handling this case via setin
> and getin. I've also ditched macros, because that code couldn't support new
> lexical scopes in the setter/getter definition. setin getin support works by
> dynamically resolving getters and setters, thus this is slower than direct
> access via assoc-in and get-in.
> Personally I have to say now that this is written, I prefer the terseness
> of:
> (set-x some-map v)
> over
> (assoc some-map :x v)
> This
> (get-x some-map)
> isn't as nice as
> (:x map)
> But it's also more explicit about how the map is being used- that a level
> indirection is required because the implementation might change.
> ;; ==========================================
> (comment
>   (accessors x y z)
>   ; {:x 4}
>   (set-x {} 4)
>   (defset x [m v]
>     (assoc (assoc m :new "new") :x v))
>   ;; {:new "new", :x {:y {:z 1}}}
>   (setin {:x {:y {:z 0}}} '(x y z) 1)
>   ;; 0
>   (getin {:x {:y {:z 0}}} '(x y z))
>   ; {:x 4, :new "new", :foo 9}
>   (let [z {:foo 9}]
>     (set-x z 4))
>   ; 10
>   (let [y {:z 10}]
>     (get-z y))
>   ; [0 1 2]
>   (map get-x [{:x 0}, {:x 1}, {:x 2}]))
> (defn setter* [sym]
>   `(defn ~(symbol (str "set-" sym)) [~'m ~'v]
>      (assoc ~'m ~(keyword (str sym)) ~'v)))
> (defn getter* [sym]
>   `(defn ~(symbol (str "get-" sym)) [~'m]
>      (~(keyword (str sym)) ~'m)))
> (defmacro defset [sym args & forms]
>   (let [set-sym (symbol (str "set-" sym))]
>     `(defn ~set-sym [...@args]
>        ~...@forms)))
> (defmacro defget [sym args & forms]
>   (let [get-sym (symbol (str "get-" sym))]
>     `(defn ~get-sym [...@args]
>        ~...@forms)))
> (defn find-accessor [sym acc-type]
>   (let [ns       (or (namespace sym)
>     (str *ns*))
> sym-name (name sym)]
>     (find-var (symbol ns (str (name acc-type) "-" sym-name)))))
> (defn setin [m [sym & syms] v]
>   (let [setter (find-accessor sym :set)
> getter (find-accessor sym :get)]
>   (if syms
>     (setter m (set-in (getter m) syms v))
>     (setter m v))))
> (defn getin [m [sym & syms]]
>   (let [getter (find-accessor sym :get)]
>     (if syms
>       (getin (getter m) syms)
>       (getter m))))
> (defmacro accessors [& syms]
>   `(do
>      ~@(map setter* syms)
>      ~@(map getter* syms)))
>
> On Sat, Apr 25, 2009 at 4:42 AM, MattH <mbhut...@gmail.com> wrote:
>>
>> It's worth considering how *nested* accessors would work in the
>> context of immutability.
>>
>> The nested maps approach works really nicely, due in part to functions
>> like assoc-in:
>>
>> ; From Mark Volkmann's tutorial
>> (assoc-in person [:employer :address :city] "Clayton")
>>
>> What would the above update look like if 'address' was accessed using
>> functions like get-address and set-address?
>>
>> Functions like assoc-in clearly rely on a uniform way of getting/
>> setting fields (i.e. maps).
>>
>> My *hunch* is that the right avenue is to extend/implement clojure's
>> map classes if injecting behaviour is ever necessary. (A standard/
>> supported way to do this would be nice.)
>>
>> I'd be happy using constructor functions like (make-complex-number)
>> and (make-person) which can hide detail of their implementations, but
>> I'd also like to benefit from all that goes with the idiomatic use of
>> maps.
>>
>> (My 2c)
>>
>
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
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