Fork me on GitHub
#beginners
<
2020-02-04
>
vincent.cantin00:02:10

Is it possible to write a macro that returns the qualified name of a symbol passed as parameter? Example:

(my-macro foo)
; => this-ns/foo

(my-macro other-ns/foo)
; => other-ns/foo

noisesmith00:02:51

macros don't implicitly namespace symbols, but the ` reader-macro does

noisesmith00:02:02

but it doesn't apply to your args

vincent.cantin00:02:14

hm .. so I guess that I have to (in the macro) manually append the current ns to the symbol’s name when it is unqualified.

noisesmith00:02:40

also "current ns" in a macro can be counterintuitive

andy.fingerhut00:02:57

Yeah, is it the namespace where the macro is defined, or where it is invoked?

andy.fingerhut00:02:07

And out of curiosity, what problem are you trying to solve?

vincent.cantin01:02:29

It’s a little difficult to explain ..

vincent.cantin01:02:35

I would like to refer to external functions from inside the template as if the template was Clojure syntax.

vincent.cantin01:02:12

For example:

(defn sum [a b]
  (+ a b))

(defc my-comp [data]
  {:id :app/my-comp}
  (let [x (:number1 data)
        y (:number2 data)]
    [:div x " + " y " = " (sum x y)]))

vincent.cantin01:02:03

the let expression is just symbolic data, but I wish to have current-ns/sum and its value from the symbol sum

alexmiller02:02:15

you can resolve in terms of *ns* - is that sufficient?

vincent.cantin02:02:05

I think that would work. Thank you. I will try it tonight. (in 12 hours)

franklineapiyo11:02:22

Hi everyone. I'm just getting started with clojure...

finn.volkel14:02:11

Hey. I am debugging some code with a toplevel def and use something of the following form to try to monitor the changes.

(def ^:dynamic *a* (atom {}))

(add-watch *a* :watcher
           (fn [key atom old-state new-state]
             (prn "-- Atom Changed --")
             (prn "key" key)
             (prn "atom" atom)
             (prn "old-state" old-state)
             (prn "new-state" new-state)))

(reset! *a* {:foo "bar"})
The above works fine in a clean project, but somehow has no effect (nothing printed) in the code I am working on. Is there something I need to be aware of when using add-watch or any ideas what could be the issue?

finn.volkel14:02:48

Somethow my add-watch statement has no effect if I do

(-> *a* .getWatches keys)
I get nil.

noisesmith16:02:31

why put an atom in a dynamic var?

noisesmith16:02:31

that's weird

finn.volkel17:02:31

@ yes I don't know. haven't written the code myself. Maybe its stayed this way as a legacy. https://github.com/clojure-emacs/cider-nrepl/blob/master/src/cider/nrepl/middleware/debug.clj#L58

finn.volkel18:02:51

No there is some good reason, but I don't know exactly. Without the ^:dynamic the code fails.

noisesmith18:02:14

I'm suspicious that the failure could be related to the way the dynamic var is used - it could point to another atom in the code you care about

frederikdieleman15:02:57

Hi! Beginner question here, I'm trying to find my way through the options of serializing Clojure objects. I have a small ML model as an instance of a deftype that implements a bunch of protocols. Now that it's trained, I'd like to save it out to disk so that I can use it later on. In Python I'd either use TensorFlow's options to save to disk, or just use Pickle if it's an class I defined myself. I don't seem to find an equivalent to Pickle that works out of the box for custom objects in Clojure though. Am I missing something? A bit more background info: What I'm trying to save out is small neural net, implemented as a NeuralNetworkInference deftype as defined in Dragan Rocks' blogpost: https://dragan.rocks/articles/19/Deep-Learning-in-Clojure-From-Scratch-to-GPU-12-A-Simple-Neural-Network-Training-API. So it's basically a bunch of Neanderthal matrices and some function definitions wrapped in an interface. Thanks! 🙂

blueberry15:02:47

@frederikdieleman You do not need to serialize functions etc, just data - your weight and bias matrices. Until I provide an out-of-the-box solution for that (in Deep Diamond) please see what Kamil Toman provided as a DIY solution https://github.com/katox/neanderthal-stick

frederikdieleman16:02:16

Neanderthal-stick doesn't seem to be on clojars, so had to clone it. In the end it did turn out to be the easiest solution. Worked great, only thing I still needed to add was a way to serialize the type of activation function each layer has. On a sidenote: I didn't find the repo of the code you created in the "Deep Learning from Scratch to GPU" series and hence don't know what kind of licence you've put on it. Is it ok if I use it in a repo of mine? (with mention of source of course)

noisesmith16:02:20

@frederikdieleman java comes with serialization, but for clojure data you can use transit and extend it for native types as needed

noisesmith16:02:49

transit will pick up the custom data readers / writers for any defrecord / deftype

k.i.o16:02:44

careful with java serialization tho, it's a mess and leaky, better to avoid it

noisesmith16:02:13

this is an example of using java's built in serialization, fwiw - I agree that it has serious problems

(import ( FileOutputStream
                 FileInputStream
                 ObjectOutputStream
                 ObjectInputStream
                 IOException))

(require '[ :as io])

(defn to-file
  [file-name & data]
  (with-open [file (FileOutputStream. file-name)
              stream (ObjectOutputStream. file)]
    (doseq [d data]
      (.writeObject stream d))))

(defn from-file
  [file-name]
  (with-open [file (FileInputStream. file-name)
              stream (ObjectInputStream. file)]
    (into []
          (take-while (complement #{::done}))
          (repeatedly
           #(try
             (.readObject stream)
             (catch IOException _ ::done))))))

noisesmith16:02:20

I think the problems with java serialization are less severe with clojure (especially if you commit to reading and writing from the same clojure version) but transit is still more compact and it's human readable

frederikdieleman09:02:45

Thanks for the help! In any case it's just for short-term saving of my own ML models, so not too worried about potential risks with it. Unfortunately Neanderthal matrices are not serializable, so will have a look at one of the other options.

noisesmith18:02:09

the obvious workaround would be to convert neanderthal matrices into a tag plus an array of arrays (that should serialize very efficiently...) - but I'm sure it's even simpler in a proper clojure serialization lib

nate_clojurians18:02:39

there's also nippy, fwiw

michael.e.loughlin20:02:26

I'm using nippy in my hobby project

michael.e.loughlin20:02:56

it works out of the box with all Clojure standard types AFAIK, and serialises to bytes

admin05521:02:29

As a Clojure beginner, I just discover condp and wow ! 😮 I updated my "Perfect number" exercism and now it's more concise than cond https://exercism.io/tracks/clojure/exercises/perfect-numbers/solutions/4e1654ede3b945518f1e0a4b0d18b0cf

hindol.adhya04:02:53

Wait till you realise a special case condp = is equal in power to switch/case in most languages. condp can do so much more.