Clojure: Defining a symbol in another namespace - clojure

Context
This is the contents of init.clj
(ns init)
(defn get-hotswap []
(filter #(= (ns-name %) 'hotswap) (all-ns)))
(let [x (get-hotswap)]
(let [old-ns *ns*]
(if (empty? x)
(do
(create-ns 'hotswap)
(in-ns 'hotswap)
(def global-kv-store (clojure.core/atom {}))
(in-ns (ns-name old-ns)))
(println "Found Hotswap"))))
Now. hotswap/global-kv-store does not exist, but init/global-kv-store does exist.
Question
How do I fix this? I want to be able to
create a new namespace hotswap
and then define a new variable global-kv-store in it
Thanks!

You can try this:
(if-not (find-ns 'hotswap)
(intern (create-ns 'hotswap) 'global-kv-store (atom {})))

Related

clojure cannot define same function in different namespace? not possible

i have one file "map_reduce2.clj" and another "map_reduce3.clj", the both defin function "map-reduce" themself.
now i want to use namespace of "map_reduce2.clj" in "map_reduce3.clj", but when i press "C-c C-k" in emacs to compile the "map_reduce3.clj",
error happens: "parse-line already refers to: #'chapter12.map-reduce2/parse-line in
namespace: chapter12.map-reduce3" , but this doesn't make any sense.
; map_reduce3.cli
(ns chapter12.map-reduce3
(:use clojure.java.io)
(:require [chapter12.map-reduce2 :as c12]))
(def IGNORE "_")
(defn parse-line [line]
(let [tokens (.split (.toLowerCase line) " ")]
[[IGNORE (count tokens)]]))
(defn average [numbers]
(/ (apply + numbers)
(count numbers)))
(defn reducer [combined]
(average (val (first combined))))
(defn average-line-length [filename]
(c12/map-reduce parse-line reducer (line-seq (reader filename))))
; map_reduce2.clj
(ns chapter12.map-reduce2
(:use clojure.java.io))
(defn combine [mapped]
(->> (apply concat mapped)
(group-by first)
(map (fn [[k v]]
{k (map second v)}))
(apply merge-with conj)))
(defn map-reduce [mapper reducer args-seq]
(->> (map mapper args-seq)
(combine)
(reducer)))
(defn parse-line [line]
(let [tokens (.split (.toLowerCase line) " ")]
(map #(vector % 1) tokens)))
(defn sum [[k v]]
{k (apply + v)})
(defn reduce-parsed-lines [collected-values]
(apply merge (map sum collected-values)))
(defn word-frequency [filename]
(map-reduce parse-line reduce-parsed-lines (line-seq (reader filename))))
images of the the error
This probably means you have dirty REPL state. Maybe you moved the function parse-line from one namespace to the other. I suggest restarting the REPL, or unload parse-line from map-reduce3: How to unload a function from another namespace?.

How can I convert a Clojure namespace to a string?

I'm trying to pretty print a list of namespaces:
(doseq [x (all-ns)] (println x))
This prints each namespace as #<Namespace xxxxx>. I would like to get each namespace as xxxxx (that is without the #<Namespace>. I tried to (name x), (symbol x) but I get ClassCastException clojure.lang.Namespace cannnot be cast to java.lang.Named, etc.
(doseq [x (all-ns)] (println (name x)))
(doseq [x (all-ns)] (println (str x)))
(doseq [x (all-ns)] (println (namespace x)))
How can I get the namespace as a string?
Use ns-name:
(doseq [x (all-ns)] (println (ns-name x)))
Note that ns-name gives you a symbol. So if you want a string just use (str (ns-name ns)).
Use the ns-name function:
(doseq [x (all-ns)] (println (ns-name x)))
Namespace function docs can be found here
Best of luck.

macro always throw "UnmatchedDelimiter" if given anon function

I wrote a macro to handle http response
(defmacro defhandler
[name & args]
(let [[docstring args] (if (string? (first args))
[(first args) (next args)]
[nil args])
args (apply hash-map :execute-if true (vec args))]
`(do
(def ~name
(with-meta (fn [scope# promise#]
(let [e# (:execute-if ~args)
ei# (if (fn? e#)
(e# scope#)
(boolean e#))]
(when ei#
(.then promise# (fn [result#]
(let [{:strs [http-status# value#]} result#
the-func# ((keyword http-status#) ~args)]
(the-func# scope# value#))))))) {:structure ~args}))
(alter-meta! (var ~name) assoc :doc ~docstring))))
So I can do
(defhandler my-handler
:200 (fn [$scope value] (set! (.-content $scope) value)))
But that throws "UnmatchedDelimiter" at line 1, but if I try with a named function:
(defn my-func [$scope value] (set! (.-content $scope) value))
(defhandler my-handler
:200 my-func)
It works ok. I'm just curious, is that a normal behaviour?
That is not the behavior I see when I try your example, nor does it seem very likely. I suggest checking that the forms you pasted here are exactly the ones that produce an error; I suspect your actual anonymous function included one too many )s.

Setting a debug function from the command line in Clojure

I have a namespace like this:
(ns foo.core)
(def ^:dynamic *debug-fn*
"A function taking arguments [bar baz]"
nil)
(defn bar-info
[bar _]
(println bar))
(defn baz-info
[_ baz]
(println baz))
(defn do-stuff
[bar baz]
(when *debug-fn* (*debug-fn* bar baz)))
(defn -main
[& {:keys [debug-fn]}]
(binding [*debug-fn* (symbol debug-fn)] ;; THIS WON'T WORK!
(do-stuff 27 42)))
What I would like to do is allow a debug function to be specified from the command line like this: lein run bar-info or lein run baz-info.
I'm not sure how to take the string specified as a command-line argument and turn it into the namespace-qualified function to bind. Do I need a macro to do this?
Use ns-resolve, you will need to specify namespace where your function is defined though.
user=> (defn f [n] (* n n n))
#'user/f
user=> ((ns-resolve *ns* (symbol "f")) 10)
1000
Use alter-var-root:
user=> (doc alter-var-root)
-------------------------
clojure.core/alter-var-root
([v f & args])
Atomically alters the root binding of var v by applying f to its
current value plus any args
nil
user=> (alter-var-root #'*debug-fn* (fn [v] (fn [x] (println x) x)))
#<user$eval171$fn__172$fn__173 user$eval171$fn__172$fn__173#7c93d88e>
user=> (*debug-fn* 1)
1
1
Though I've accepted Guillermo's answer above, I figured that it might also be useful to add the solution I ended up going with:
(def debug-fns
{:bar-info (fn [bar _] (println bar))
:baz-info (fn [_ baz] (println baz))
(def active-debug-fns (atom []))
(defn activate-debug-fn!
[fn-key]
(let [f (debug-fns fn-key)]
(if f
(swap! active-debug-fns conj f)
(warn (str "Debug function " fn-key " not found! Available functions are: "
(join " " (map name (keys debug-fns))))))))
(defn debug-fn-keys
[args]
(if (args "--debug")
(split (or (args "--debug") "") #",")
[]))
(defn do-stuff
[bar baz]
(doseq [f #active-debug-fns]
(f bar baz)))
(defn -main
[& args]
(let [args (apply hash-map args)]
(doseq [f (debug-fn-keys args)]
(activate-debug-fn! (keyword k)))
(do-stuff 27 42)))
So now you can say something like lein run --debug bar-info to get info on bars, or lein run --debug bar,baz to get info on both bars and bazes.
Any suggestions to make this more idiomatic will be happily accepted and edited in. :)

clojure: adding a debug trace to every function in a namespace?

just started using log4j in one of my home-projects and I was just about to break out the mouse and cut-and-paste (trace (str "entering: " function-name)) into every function in a large module. then the voice of reason caught up and said "there has simply got to be a better way"... I can think of making a macro that wraps a whole block of functions and adds the traces to them or something like that? Any advice from the wise Stack-overflowing-clojurians?
No need for a macro:
(defn trace-ns
"ns should be a namespace object or a symbol."
[ns]
(doseq [s (keys (ns-interns ns))
:let [v (ns-resolve ns s)]
:when (and (ifn? #v) (-> v meta :macro not))]
(intern ns
(with-meta s {:traced true :untraced #v})
(let [f #v] (fn [& args]
(clojure.contrib.trace/trace (str "entering: " s))
(apply f args))))))
(defn untrace-ns [ns]
(doseq [s (keys (ns-interns ns))
:let [v (ns-resolve ns s)]
:when (:traced (meta v))]
(alter-meta! (intern ns s (:untraced (meta v)))
#(dissoc % :traced :untraced))))
...or something similar. The most likely extra requirement would be to use filter so as not to call trace on things which aren't ifn?s. Update: edited in a solution to that (also handling macros). Update 2: fixed some major bugs. Update 4: added untrace functionality.
Update 3: Here's an example from my REPL:
user> (ns foo)
nil
foo> (defn foo [x] x)
#'foo/foo
foo> (defmacro bar [x] x)
#'foo/bar
foo> (ns user)
nil
user> (trace-ns 'foo)
nil
user> (foo/foo :foo)
TRACE: "entering: foo"
:foo
user> (foo/bar :foo)
:foo
user> (untrace-ns 'foo)
nil
user> (foo/foo :foo)
:foo