What function/macro to check what namespaces are currently 'used' and how to check if one in particular is used? - namespaces

Is there a function/macro in Clojure to check what namespaces are currently 'used'? Which one? So I don't mean 'what namespace are we currently in' but for example, I want to find out if 'clojure.contrib.string' is currently 'used' as in (use 'clojure.contrib.string). I don't mean 'required'.
How does one write a function that give true when for example 'clojure.contrib.string (the name of the namespace provided via a symbol) is used and false otherwise?
(defn ns-used? [name] (...)

all-ns as suggested by kotarak, is close to what you are looking for, but it also gives you all the namespaces that have been required without having been referred.
Otherwise ns-refers gives you a map of all the functions that are referred in the namespace. Similar and possibly also of interest are ns-map and ns-imports which gives you a mapping of all the imported classes or records.
If you want to strictly find all the namespaces from which functions have been referred, you could do something like this:
(defn ns-used? [ns]
(let [referred-namespaces (set (map (fn [[k v]] (:ns (meta v))) (ns-refers *ns*)))]
(contains? referred-namespaces (find-ns ns))))
If you are happy to check if the namespace has been required or used you could do
(defn ns-used-or-required? [ns]
(contains? (set (all-ns)) (find-ns ns)))
You will have to pass the symbol in quoted:
(ns-used? 'clojure.core)

all-ns for some suitable definition of 'used'.
ns-refers for some other definition of 'used'.

Related

Clojure/Clojurescript: Argument to resolve must be a quoted symbol

I'm attempting to use a string saved in a variable to call a function like so:
(defn update-product-list [] "Test")
(defn handle-state-change [action]
((resolve (symbol action))))
(handle-state-change "update-product-list")
However, this gives me the following error: Assert failed: Argument to resolve must be a quoted symbol
I've also tried changing the above line to:
((resolve (quote (symbol action))))
But this still gives an error. I also tried changing it just to:
((resolve 'action))
But this gives a different error I don't quite understand: js/action is shadowed by a local. I don't want to override the function just call it. Not sure where I'm going wrong. I've looked at a few examples, but can't see to pin it down.
ClojureScript supports :advanced optimization, in which Google Closure Compiler will rename, inline, or eliminate (unused) functions in order to implement minification. In short, the name of the function you want to look up will, in general, simply no longer exist under :advanced.
Because of this, ClojureScript's resolve is a compile-time facility (a macro requiring a literal quoted symbol).
If you are using :simple or self-hosted ClojureScript, more options are available to you because the support needed persists into runtime. For example Planck has a planck.core/resolve that behave's like Clojure's resolve. A similar approach is possible in Lumo, and similar facilities can be fashioned if using :simple.
In general though, given :advanced, if you need to map strings to a set of functions, you need to somehow arrange to have a static mapping constructed at compile time to support this (the set of functions must be known a priori, at compile time).
If you have a namespace (the name of which is statically known at compile time) which defines functions that need to be dynamically called via strings, you could consider making use of ns-publics:
cljs.user=> (ns foo.core)
foo.core=> (defn square [x] (* x x))
#'foo.core/square
foo.core=> (in-ns 'cljs.user)
nil
cljs.user=> (when-some [fn-var ((ns-publics 'foo.core) (symbol "square"))]
(fn-var 3))
9
This will work under :advanced. The mapping constructed by ns-publics is static; built at compile-time. If you have multiple namespaces that need such treatment, you could merge several calls to ns-publics to build a larger map.
The advantage of this approach is that the code involved is pretty short and requires little maintenance. The disadvantage is that it dumps all of the public vars of the namespace (foo.core in this example) into your generated code (and the generated code for vars is somewhat verbose). Another disadvantage is that you need to statically know the namespace(s) involved at compile time.
If you need to further minimize generated code size, you could just build / maintain a simple static map from string to function value as in
(def fns {"square" foo.core/square})
and use it appropriately, keeping it up to date as your codebase evolves.
Another option would be to mark the functions that you need to access using ^:export meta, and then to call those functions using JavaScript interop. For example if you define the function this way
(defn ^:export square [x] (* x x))
then you can use strings / interop to lookup the function and call it at runtime. Here's an example:
((goog.object/getValueByKeys js/window #js ["foo" "core" "square"]) 3)
The use of ^:export and :advanced is covered here. If you know that you are using :simple or less, then you can simply use JavaScript interop to call the functions of interest, without needn't to use ^:export.
Note that there is no general solution that would let you look up a function by name at runtime under :advanced without somehow putting some aspect of that function into your code at compile time. (In fact, if a function is not referenced in a way that Google Closure Compiler can statically, see, the function implementation will be completely eliminated as dead code.) In the above, ns-publics grabs all the vars for a namespace at compile time, rolling your own lookup map sets up static code to refer to the function value, and using ^:export statically arranges to make the name of the function persist into runtime.
You need to use it like this:
((resolve 'inc) 5)) => 6
or, deconstructed a bit:
(let [the-fn (resolve 'inc)]
(the-fn 7))
=> 8
If you have the function name as a string, use the symbol function to convert from string => symbol (from clojuredocs.org):
user=> ((-> "first" symbol resolve) [1 2 3])
1
And, never forget the Clojure CheatSheet!

eval-str in ClojureScript with public structure as a parameter

My problem requires applying custom logical functions to a structure. Those functions are stored in a database as a string. I have data like this:
(def fruits {:apple {:color "red" :ripe? true}
:strawberry {:color "red" :ripe? false}})
And I have this cond check:
"(some (fn [fruit] (-> fruit val :ripe? false?)) fruits)"
Unfortunatelly I can't get this right even though I tried various approaches:
1)
(cljs/eval-str (cljs/empty-state)
"(some (fn [fruit] (-> fruit val :ripe? false?)) my.main/fruits)"
""
{:eval cljs/js-eval}
identity)
This works yet it yields errors:
WARNING: No such namespace: my.main, could not locate my/main.cljs, my/main.cljc, or Closure namespace "" at line 1
WARNING: Use of undeclared Var my.main/fruits at line 1
Also this approach obviously wouldn't work in advanced compilation.
2) I tried to leverage approach that works in Clojure:
((eval
(read-string
"(fn [fruits]
(some (fn [fruit] (-> fruit val :ripe? false?)) fruits))"))
fruits)
I can't see why this wouldn't work in advanced compilation. Unfortunatelly it simply returns nil every single time.
Is it just me who fails to come up with a solution or is CLJS just not capable of doing that yet?
I suspect your going to have a vary hard time achieving your requirement using
this approach. The big problem is likely going to be due to the way
clojurescirpt needs to be compiled into javascript (using Google closure). You
can probably get it to work doing some clever stuff with externals and using low
level javascript interop and the closure library, but I suspect it will be hard
work.
A couple of alternative approaches which may be worth considering
Store the data in the database in edn format. Using edn, you may be able to
read it into a var and then execute it
Change direction - do you really need to store complete functions or could you
instead define a type of DSL which obtains parameters from the database which
will provide the necessary level of dynamic execution.
Could you have some sort of pre-processing solution i.e. write the function in
clojurescript, but use closure functionality to compile that to javascript and
insert that into the database instead of the raw clojurescript. This would
make the initial storing of the data more complex, but may simplify calling
the dynamic functions at runtime. You could even include some code checks or
validation to reduce the likelihood of code taken from the database doing the
wrong thing.
There are so many risks associated with using totally dynamic code it is almost
never a good solution. Aside from the numerous security issues you have with
this approach, you also have to deal with elegantly handling problems arising
from buggy definitions being inserted into the database (i.e. a buggy function
definition which crashes your app or corrupts data. If you just have to have the
ability to dynamically execute unknown code, then at least edn provides some
additional protection you don't get with eval-str - but really, just don't do
it.
After hours of experiments and struggling with evaluating functions from strings I decided to write DSL.
In database I store string with a map containing these parameters:
:where? - vector containing path to a desired answer.
:what? - answer(s) I'm looking for.
:strict? (optional) - A boolean. If true then answers need to be exactly the same as :what? rule (order doesn’t matter).
Then I just evaluate that simple cljs file. It works both on advanced and none optimization mode.
(defn standard-cond-met? [{:keys [what? where? strict?]
:or {strict? false}}]
(let [answer (get-in answers (conj where? :values))]
(if strict?
(= (sort what?) (sort answer))
(clojure.set/subset?
(set what?)
(set answer)))))

Can name munging be avoided for an interop call in ClojureScript?

In advanced compilation
(js/console.log "HELLO"
js/window.navigator.msSaveBlob
(.. js/window -navigator -msSaveBlob)
(aget js/window "navigator" "msSaveBlob")
js/console.log)
=>
HELLO undefined undefined function function
I think this means that js/console has some provided externs, but navigator does not (or at least not the ms specific stuff).
AFAIK the only way to avoid this is to create some externs? But this seems unnecessarily obtuse; why would you ever want js/anything to be munged?? Wouldn't it make make more sense to never munge js/anything interop?
System functions are not munged; only your own functions are. You probably want (.log js/console ...) ?
For de-munging your own functions, place ^:export between the defn and the function name to export its name intact.
Here is more information.
All see the section called "munging" here.

find about about the type of function parameters

can i somehow find all functions/macros that take a specific type of parameter ?
for example, what function accepts a Namespace object as parameter ?
(this is because i can create a namespace and store it in a var, but i don't know where i could use that var; what function might i pass that var to ?)
here is some code:
user=> (def working-namespace (create-ns 'my-namespace))
#'user/working-namespace
;i created a namspace and want to use it later
user=> (class working-namespace)
clojure.lang.Namespace
; out of curiosity i found out that "working-namespace" is a Namespace object
user=> (ns working-namespace)
nil
working-namespace=>
; but how do i switch to it ? this didn't do what i wanted...
user=> (refer working-namespace)
java.lang.ClassCastException: clojure.lang.Namespace cannot be cast to clojure.lang.Symbol (NO_SOURCE_FILE:0)
; this did not work either as my expectations
user=> (the-ns working-namespace)
#<Namespace my-namespace>
user=> (class (the-ns working-namespace))
clojure.lang.Namespace
; great, this gave me the same thing, a Namespace
hence the question: how do i use it dynamically (that's why i had put my namespace into a var) ? how do i get something useful for me from a var that points to a namespace ?
i can try look around for functions that make use of a Namespace object or that convert it to something else. i did and only found "intern". searching by hand not seems not that promising
what if i have this problem a million time ? is there an automated way to get me what i'm looking for without having to ask around each time ?
In Clojure 1.2 and previous function arguments dont have types. every function argument is an object. So the question really becomes "how do i find functions that will cast the object I pass them into this type. so searching for type hints will find some of them, though it wont get you everything. I wish it where more possible to answer this in general.
starting with 1.3 (current dev branch 9/2010) function paramerters and return types can have a defined type and will be passed/returned as that type instead of being cast to object and then cast on the other side. This drops one of the zeros from the exacution time of numerical functions with the important limitation that it only works for :static functions and only with direct calls (ie: not through map/reduce/filter/etc.) There is not a lot published on this change yet though it has the important breaking change that integers are no longer boxed by default and integer (actually Long) overflow throws an exception. you can read more here
(defn ^:static fib ^long [^long n]
(if (<= n 1)
1
(+ (fib (dec n)) (fib (- n 2)))))
so after 1.3 is released and widely adopted you will see code with more commonly defined types because they will offer a big speed benefit and then you will be able to find more functions by argument type though still not all of them.
At the same lecture where I learned about function argument types, Rich mentioned plans in the distant Clojure future (after 'Clojure in Clojure') about better support for exposing the compiler internals to tools such as IDEs. So there is hope that someday you will get a real answer to this question.
Dynamic languages make this slightly more difficult in practice and a lot harder in theory.
You already got a good answer from Arthur, so I'll only answer the "how do i get something useful for me from a var that points to a namespace ?". From (doc ns), note that it says unevaluated:
user=> (doc ns)
-------------------------
clojure.core/ns
([name docstring? attr-map? references*])
Macro
Sets *ns* to the namespace named by name (unevaluated), creating it
Now there's something you could do with in-ns if you want (the whole namespace object -> string -> symbol conversion is probably stupid, but enough to illustrate my point):
user=> (in-ns (symbol (str working-namespace)))
#<Namespace my-namespace>
my-namespace=>
I don't think you can do that without a lot of hackery in a dynamic language. If you want to now what function that take namespaces look at the documentation of the namespace stuff.
For example cleaning namespaces or reload them.
You wrote:
user=> (ns working-namespace)
nil
working-namespace=>
; but how do i switch to it ? this didn't do what i wanted...
But you did switch to the working-namespace namespace (that's why the prompt changed), so I'm not clear as to what "you wanted".
As I noted earlier, you need to present the ultimate problem are you trying to solve. It's entirely likely that messing with namespace objects won't be the solution.

Is there any problem with namespacing clojure keywords in a non-existent namespace?

Should I feel wary about creating clojure keywords which have non-existent namespaces?
An example would be :foo/bar, where namespace foo doesn't actually exist. This seems to be possible because these keywords behave like literals. I couldn't find any problems doing this in the REPL, but I'm concerned about possible problems with AOT compilation.
A namespace will in fact not be created simply because a keyword or symbol is encountered which would "belong" to it, as the following interaction at a fresh REPL illustrates:
; SLIME 2010-05-06
user> (-> (.getNamespace :user/foo) symbol)
user
user> (-> (.getNamespace :user/foo) symbol the-ns)
#<Namespace user>
user> (-> (.getNamespace :bar/foo) symbol the-ns)
; java.lang.Exception: No namespace: bar found
However, this is no cause for worry. A keyword's or symbol's "namespace" field is just an interned string; there is no reference back to the corresponding namespace object involved even if one exists. In fact, as can be seen above, the .getNamespace method of keywords and symbols returns a string and one has to jump a few hops to get to the actual namespace from that.
Trying to resolve a namespace-qualified symbol with the resolve function is safe too. That's regardless of whether the namespace actually exists; if it doesn't, nil is returned, as in the case where it does exist, but holds no Var of the given name. ns-resolve, in contrast, will throw an exception like the one mentioned in the snippet from the REPL above if it can't find the given namespace.