Hi again, 2009/4/20 Timo Mihaljov <noid....@gmail.com>
> > Laurent PETIT wrote: > > What do others think about these 2 above statements ? > > > > The standard OO approach to information hiding would be private > fields > > and accessor methods. Any suggestions for the One True Clojure > Pattern > > that addresses the same problem? > > > > > > I think accessor methods. > > Based on our discussion so far, I would use the following approach. In > the spirit of defn-, I appended a dash after field names that should be > accessed via accessor functions. To simplify a little bit (both from a library implementor and user perspective), why not get rid of the appended dash - ? Indeed, having an appended dash suggests to me (so it's not apparent from the examples) that the user will have to access, for a same object, data sometimes from key accessors, and sometimes from specific function accessors. I would suggest to keep it simpler for the user : either the lib states it is safe for him to use key accessors, either the lib states the user must use the function accessors provided. With this logic, either all keys are public (first case) or private (second case). > This is similar to the Python idiom of > prefixing "private" members with an underscore to prevent _accidental_ > direct modification. The symbols are also used as the initial versions > of the getter functions. This way there's so little code that no macros > are needed. I'm pretty sure this has been done gazillons of time before (and maybe it's already in clojure-contrib and I don't know about it), but here is a little macro that would still get rid of the duplications in your code: (defn defstruct-type-fn [name public-key-names-coll private-key-names-coll] `(do (defstruct ~name ~@(map (comp keyword str) public-key-names-coll) ~@(map (comp keyword str) private-key-names-coll)) ~@(into () (map (fn [k] `(defn ~k [st#] (~(keyword (str k)) st#))) public-key-names-coll)))) (defmacro defstruct-type ; sorry, no better name at the time of writing "creates a struct via defstruct named name and whose keys a constructed from key-names (names of the keys without the prefix column). Creates as well accessor functions named after public-key-names-coll. Optionally a sequence of private keys can also be passed" ([name public-key-names-coll] (defstruct-type-fn name public-key-names-coll nil)) ([name public-key-names-coll private-key-names-coll] (defstruct-type-fn name public-key-names-coll private-key-names-coll))) This way, you can rewrite your code : ;; ==== OLD ===== ;; Library (defstruct person :first-name- :last-name-) (defn new-person [full-name] (let [[first-name last-name] (.split full-name " ")] (struct person first-name last-name))) (def first-name :first-name-) (def last-name :last-name-) (defn full-name [the-person] (str (first-name the-person) " " (last-name the-person))) ;; ==== NEW ===== ;; Library (defstruct-type person [first-name last-name]) (defn new-person [full-name] (let [[first-name last-name] (.split full-name " ")] (struct person first-name last-name))) (defn full-name [the-person] (str (first-name the-person) " " (last-name the-person))) I don't know if the whole common lisp "structs" library has been ported to clojure. And, as you asked, I'm not sure whether this would be a good think to port it, and if there's another idiomatic way to solve the same problems. Regards, -- Laurent > > ;;; Initial version > > ;; Library > (defstruct person :full-name-) > > (defn new-person [full-name] > (struct person full-name)) > > (def full-name :full-name-) > > ;; Client > (def p (new-person "James Bond")) > (println (full-name p)) > > > ;;; Modified version > > ;; Library > (defstruct person :first-name- :last-name-) > > (defn new-person [full-name] > (let [[first-name last-name] (.split full-name " ")] > (struct person first-name last-name))) > > (def first-name :first-name-) > (def last-name :last-name-) > > (defn full-name [the-person] > (str (first-name the-person) " " (last-name the-person))) > > ;; Client > (def p (new-person "James Bond")) > (println (last-name p)) > (println (full-name p)) > > How does this code look like to a experienced Clojure programmer? Does > it seem to be in the spirit of the language? > > -- > Timo > > > > --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---