On Thu, Aug 6, 2015 at 10:39 AM, kirby urner <kirby.ur...@gmail.com> wrote:

> (ns test-project.quadrays)
>
> (defprotocol Ops
> (q-add [this other])
> (q-sub [this other])
> (q-len [this])
> (q-neg [this])
> (q-norm [this]))
>
> (defrecord Quadray [OA OB OC OD]
> Ops
> (q-norm [this]
> (let [[a b c d] [(:OA this) (:OB this) (:OC this) (:OD this)]
> [x] [(min a b c d)]]
> (Quadray. (- a x) (- b x) (- c x) (- d x))))
>
> (q-neg [this] (q-norm (Quadray. (- 0 (:OA this))
> (- 0 (:OB this) )
> (- 0 (:OC this))
> (- 0 (:OD this)))))
>
> (q-len [this] (let [[a b c d] [(:OA this) (:OB this) (:OC this) (:OD
> this)]
> [k] [(/ (+ a b c d) 4)]
> [t0 t1 t2 t3] [(- a k) (- b k) (- c k) (- d k)]]
> (* (Math/sqrt 2.0)
> (Math/sqrt (+ (* t0 t0) (* t1 t1) (* t2 t2) (* t3 t3))))))
>

Inside the implementation of a record definition, you can refer to all the
parts of a record more simply.
(:OA this) can just be OA and so on.
That means the `let` is also unnecessary here.

Note that `Quadray.` could be replaced by `->Quadray`.  Both forms are
acceptable, but the latter is a true function and can be passed to
higher-order functions.

Also, note that `-` can be used as a unary function.  `(- 0 x)` can just be
replaced with `(- x)`.

The larger question here is whether records/protocols are really the right
tool for the job here.  Clojure gives you a lot of ways to do a given
thing; newcomers are often attracted to records/protocols as one of the
more familiar OO-like constructs, but that doesn't mean they are always the
right fit.

Protocols are valuable for polymorphism, i.e., implementing the same
functions over several different concrete representations.  So unless you
plan to have multiple representations of Quadrays, there's no real reason
to use protocols.  And based on your naming scheme, there's absolutely no
indication that you have any intention of having these functions ever apply
to other data structures.  Remember, Clojure eschews encapsulation (no
reason for it, since everything is immutable), therefore, a function can
get exactly the same access to the so-called "privileged bits".  All your
protocol definitions as written above could simply be regular functions.

A related choice is whether to implement Quadray as a record, or just a
function that builds a map, i.e.,
(defn quadray [oa ob oc od] {:oa oa :ob ob :oc oc :od od})
or if you need a "type" to contrast it with other structures
(defn quadray [oa ob oc od] {:tag :quadray :oa oa :ob ob :oc oc :od od})

The tradeoffs are subtle.  Records give you improved performance when
accessing the "member variables", the ability to type hint the members
(which you arguably want to do here, since all the members are doubles, and
that typing the members could potentially improve your arithmetic
performance).  But records currently have a "performance bug" in 1.7 that
makes them slower than plain maps when used as keys in other maps or sets,
because they don't cache their hash values the way regular maps do.
Records are almost interchangeable with maps, but there are a few ways they
are not -- for example, records by default can't be used as a function of
their keys the way maps can.  Using plain maps also gives you a simpler
serialization story.

So, there's nothing really wrong with using records/protocols, but be aware
that there are other choices with other strengths/weaknesses.

Also, don't forget to explore the test framework versus global defs and
print statements.

-- 
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
Note that posts from new members are moderated - please be patient with your 
first post.
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to