Functions referenced in macro-expansions cannot be internal?

56 views
Skip to first unread message

hiskennyness

unread,
Apr 1, 2016, 1:37:10 AM4/1/16
to Clojure
With Jellz (ne Cells in CL) I want to make reading an attribute of an object seem like a normal function call, but reading a cell actually looks like this:

(defn- svr [slot me] ;; svr = slot-value-read, me = short version of "self"
  (when-let [sval (slot @me)]
    (cond
     (jz-ref? sval)
     (case (type @sval)
       :jzi (:val @sval)
       :jzf ((:rule @sval) me)
       (error "jz-ref? type unknown" ))
     :else sval)))

svr is internal because I plan to hide it. Instead of coding (svr :mass kenny) I want to code (mass kenny). And instead of hand-coding:

(defn mass [me] (svr :mass me))

...I want to code (jz/def-jzo-slot :mass).

(defmacro def-jzo-slot [slot]
  `(defn ~(symbol (subs (str slot) 1)) [~'me]
     (com.tiltontec.jellz.api/svr ~slot ~'me)))

That worked fine until I moved my testing hacks into a proper test file in the test hierarchy and Clojure complained that svr was internal (I forget the exact language).

I broke down and made it defn instead of defn-, but was something else going on? I am used to Common Lisp which sees what I am up to and worries about the symbol being defined in the Cells package, not the package into which the macroexpansion will be happening.

I always thought that was very clever and classically XWIW (exactly what I want), btw.

This is not a big deal, but did I miss some way of keeping svr internal?

-kt

Erik Assum

unread,
Apr 1, 2016, 2:41:22 AM4/1/16
to clo...@googlegroups.com
Not at all answering your question, but I would strongly suggest to at least deref `me` before calling the function, so it’s definition would be more like:

(defn svr [me slot]
(when-let [sval (slot me)]
(if (jz-ref sval)
(condp type @sval)
:jzi (:val @sval)
:jzf ((:rule @sval) me)
(error “jz-ref? type unknown”))
sval)))

And I’d probably extract the body of if into a separate function

(defn- body-of-if [me sval]
(if (jz-ref sval)
(condp type sval)
:jzi (:val sval)
:jzf ((:rule sval) me)
(error “jz-ref? type unknown”))
sval))

so that your svr would end up something like

(defn svr [slot me]
(when-let [sval (slot me)]
(body-of-if me @sval))

and then you’d call svr as

(svr @me slot)

This way, your functions don’t need to know that their arguments happen to be atoms/refs, and they fit nicely in with eg

(swap! atom-that-contains-me svr slot)

But I do agree with Timothy that you should probably try to keep your data structure free of atoms, and just use one atom to hold your data structure.


Erik.
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Kenneth Tilton

unread,
Apr 1, 2016, 7:04:22 AM4/1/16
to clo...@googlegroups.com
On Fri, Apr 1, 2016 at 2:41 AM, Erik Assum <er...@assum.net> wrote:
Not at all answering your question, but I would strongly suggest to at least deref `me` before calling the function, so it’s definition would be more like:

(defn svr [me slot]
   (when-let [sval (slot me)]
       (if (jz-ref sval)
          (condp type @sval)

Oooh, condp! I like it. :) Does it have some advantage over case in this bit of code?
 
             :jzi (:val @sval)
             :jzf ((:rule @sval) me)
             (error “jz-ref? type unknown”))
        sval)))

And I’d probably extract the body of if into a separate function

(defn- body-of-if [me sval]
  (if (jz-ref sval)
     (condp type sval)
           :jzi (:val sval)
           :jzf ((:rule sval) me)
            (error “jz-ref? type unknown”))
     sval))

so that your svr would end up something like

(defn svr [slot me]
    (when-let [sval (slot me)]
       (body-of-if me @sval))

and then you’d call svr as

(svr @me slot)

Well, I am still getting used to this functional state game, but the way the library works is that cells get brought up to date with a new model input JIT, so simply reading a cell-manged attribute could force the map impleneting "me" to be regenerated, in which case I need the ref so I can ref-set it. But...

I just realized every cell has to be a ref. There are *is* at least one internal model attribute that changes (the status as nascent, alive, dying, or dead) but that could be a ref... I will look at whether I even need models to be refs.

Parallelized cells? That would be cool, though for my applications single-threaded has been more than fast enough.

Thx for the input!

-kt


You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/nQyV1ZMdcwk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Kenneth Tilton
Founder/Developer
TiltonTec
54 Isle of Venice Dr
Fort Lauderdale, FL 33301

@tiltonsalgebra


"In a class by itself." -Macworld


Erik Assum

unread,
Apr 1, 2016, 8:37:13 AM4/1/16
to clo...@googlegroups.com
On condp, case etc. 

Alex Miller wrote a blog post on their performance a while ago:

Erik. 
-- 
i farta
Reply all
Reply to author
Forward
0 new messages