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

Reply via email to