How do I access the name of the current namespace? - clojurescript

It seems that the *ns* object is available all the time under Clojure but not under ClojureScript. Is there an alternative way to access the name of the current namespace?
Motivation
I have a slew of calls like
(define-subscription ::something :other-namespace/something)
in which the two occurrences of something are redundant. I’d like to be able to write this in a more succinct form like (define-sub 'something), but in order to turn that shortened form into the full form I’d need to have a way to refer to the keyword ::something without using the :: syntactic sugar. It would be possible just to hard-code in the namespace name, but that feels unsatisfying.

You can read the metadata associated with a var of the namespace you are interested in:
(defn get-current-namespace []
(-> #'get-current-namespace meta :ns))
Or if you don't want to declare this function in the namespace itself, but need it as a utility method, you can create one like:
(defn namespace-of-var [a-var]
(-> a-var meta :ns))
which you can call like:
cljs.user> (def a "hello!")
cljs.user> (namespace-of-var #'a)
cljs.user
Practically, you can call the namespace-of-var function from another function, passing in the function's own name as var parameter:
(defn function-in-another-namespace []
(let [current-namespace (namespace-of-var #'function-in-another-namespace)]
(prn (str "current namespace: " current-namespace))))

With a macro you should be able to do it:
(defmacro defsub [n]
(let [x# (name n)]
`(define-subscription (keyword ~x#) (keyword "other" ~x#))))
(defsub blah)

Related

Local reagent atom won't update when global ratom change

Let's say I have a component defined like this:
(defn test-comp
[timespan-ratom]
(let [[timespan-lower timespan-upper] #timespan-ratom]
(fn []
[:div.row (str "Testing" timespan-lower timespan-upper)])))
timespan-ratom is defined globally in the component that instantiates test-comp like this:
(def timespan-ratom (ratom nil))
It's instantiated like this:
[test-comp timespan-ratom]
The first time the timespan-ratom is used to create test-comp "Testing" will be printed with the correct timespan-lower and timespan-upper value. But when the timespan-ratom is reset (reset!) the values are not updated in the test-comp component? Why is this?
It works when I change the function to this:
(defn test-comp
[timespan-ratom]
(fn []
[:div.row (str "Testing" (first #timespan-ratom) (second #timespan-ratom))]))
Now the reason why I can't simply do like this is that in my actual production code I have local ratom that is dependent on the value of the timespan-ratom:
(defn test-comp
[timespan-ratom]
(let [[timespan-lower timespan-upper] #timespan-ratom
selected-time (ratom timespan-upper)]
(fn []
,,,)))
I.e. the initial value of selected-time should be the timespan-upper value defined by the timespan-ratom. The selected-time ratom is then changed locally from the test-comp component.
How can I solve this?
Remove the inner function nesting from test-comp:
(defn test-comp
[timespan-ratom]
(let [[timespan-lower timespan-upper] #timespan-ratom]
[:div.row (str "Testing" timespan-lower timespan-upper)]))
When you use an inner function with no arguments, the component can never receive the updated ratom, so it will forever hold on to the first value it got from the ratom on the first render. Also, you don't need the inner function here, because you don't have any local state.
If you do have local state (some state that needs to be remembered over the lifetime of the component), update your component so the inner function has the same arguments as the outer function and dereference the atom in the inner function:
(defn test-comp
[ratom]
(let [x "local-state"]
(fn [ratom]
(let [v #ratom]
[:div x v]))))

How do I perform a function with side-effects over a vector?

The say-hello-to-first-person works fine, why doesn't say-hello-to-everyone?
(defpartial greeting [name]
[:p.alert "Hello " name ", how are you?"])
(defn say-hello [name]
(append $content (greeting name)))
(defn say-hello-to-first-person [names]
(say-hello (first names)))
(defn say-hello-to-everyone [names]
(map say-hello names))
(say-hello-to-first-person ["Chris" "Tom" "Jim" "Rocky"])
(say-hello-to-everyone ["Chris" "Tom" "Jim" "Rocky"])
You want doseq, Clojure's "foreach":
(doseq [name names]
(say-hello name))
map doesn't work because it produces a lazy sequence: Until you actually access the items in the sequence (which you don't here), none of them will be evaluated, and side effects won't occur.
Another option is to force evaluation by wrapping dorun around the map. Thinking about why this works may help your understanding (although doseq is the idiomatic approach here).
As #edbond says in his comment, map fn don't evaluate until necessary moment because map fn returns a lazy seq.
This is the doc of map fn
Returns a lazy sequence consisting of the result of applying f to the
set of first items of each coll, followed by applying f to the set
of second items in each coll, until any one of the colls is
exhausted. Any remaining items in other colls are ignored. Function
f should accept number-of-colls arguments.
If you need to be sure that the values are evaluate in one specific part of your code you can use doall or dorun

How can I get the name of a function from a symbol in clojure?

Suppose I define x as symbol function foo
(defn foo [x] x)
(def x foo)
Can the name "foo" be discovered if only given x?
Is there a way within foo to look up the name of the function x - "foo" in this case?
(foo x)
Is there or is it possible to create a function such as:
(get-fn-name x)
foo
A similar question was asked recently on this site; see here
When you do (def x foo), you are defining x to be "the value at foo", not "foo itself". Once foo has resolved to its value, that value no longer has any relationship whatsoever to foo.
So maybe you see one possible answer to your question now: don't resolve foo when you go to do define x. Instead of doing...
(def x foo)
...do...
(def x 'foo)
Now if you try to get the value of x, you will get foo (literally), not the value that foo resolves to.
user> x
=> foo
However, that is likely problematic, because you will probably also sometimes want to be able to get at the value that foo resolves to using x. However however, you would be able to do this by doing:
user> #(resolve x)
=> #<user$foo user$foo#157b46f>
If I were to describe what this does it would be: "get the value x resolves to, use that as a symbol, then resolve that symbol to its var (not its value), and dereference that var to obtain a value".
...Now let's do something hacky. I'm not sure I would advise doing either of these things I'm about to suggest, but you did ask Can the name "foo" be discovered if only given x?, and I can think of two ways you could do that.
Method #1: regex the fn var name
Notice what foo and x both resolve to below:
(defn foo [a] (println a))
(def x foo)
user> foo
=> #<user$foo user$foo#1e2afb2>
user> x
=> #<user$foo user$foo#1e2afb2>
Now, check this out:
user> (str foo)
=> "user$foo#1e2afb2"
user> (str x)
=> "user$foo#1e2afb2"
Cool. This only works because foo resolves to a function, which happens to have a var-like name, a name which will be the same for x because it refers to the same function. Note that "foo" is contained within the string produced by (str x) (and also by (foo x)). This is because the function's var name is apparently created with some backwards reference to the symbol that was used to initially define it. We're going to use this fact to find that very symbol from any function.
So, I wrote a regular expression to find "foo" inside that string of the function var name. It isn't that it looks for "foo", but rather that it looks for any sub-string--in regex terms, ".*"--that is preceded by a \$ character--in regex terms "(?<=\$)"--and followed by the \# character--in regex terms "(?=#)"...
user> (re-find #"(?<=\$).*(?=#)"
(str x))
=> "foo"
We can further convert this to a symbol by simply wrapping (symbol ...) around it:
user> (symbol (re-find #"(?<=\$).*(?=#)"
(str x)))
=> foo
Furthermore, this whole process could be generalized to a function that will take a function and return the symbol associated with that function's var name--which is the symbol was given when the function was initially defined (this process will not at all work nicely for anonymous functions).
(defn get-fn-init-sym [f]
(symbol (re-find #"(?<=\$).*(?=#)" (str f))))
...or this which I find nicer to read...
(defn get-fn-init-sym [f]
(->> (str f)
(re-find #"(?<=\$).*(?=#)")
symbol))
Now we can do...
user> (get-fn-init-sym x)
=> foo
Method #2: reverse lookup all ns mappings based on identity
This is going to be fun.
So, we're going to take all the namespace mappings, then dissoc 'x from it, then filter what remains based on whether the val at each mapping refers to the exact same thing as what x resolves to. We'll take the first thing in that filtered sequence, and then we'll take the key at that first thing in order to get the symbol.
user> (->> (dissoc (ns-map *ns*) 'x)
(filter #(identical? (let [v (val %)]
(if (var? v) #v v))
x))
first
key)
=> foo
Notice that if you replaced x with foo above, you would get x. Really all this is doing is returning the first name it finds that maps to the exact same value as x. As before, this could be generalized to a function:
(defn find-equiv-sym [sym]
(->> (dissoc (ns-map *ns*) sym)
(filter #(identical? (let [v (val %)]
(if (var? v) #v v))
#(resolve sym)))
first
key))
The main difference here is that the argument will have to be a quoted symbol.
user> (find-equiv-sym 'x)
=> foo
This find-equiv-sym function is really not very good. Problems will happen when you have multiple things in the namespace resolving to identical values. You could return this list of symbols that resolve to identical things (instead of just returning the first one), and then process it further from there. It would be simple to change the current function to make this work: delete the last two lines (first and key), and replace them with (map key).
Anyways, I hope this was as fun and interesting for you as it was for me, but I doubt whether either of these hacks would be a good way of going about things. I advocate my first solution.
It's not clear why you would want to do this - when you do (def x foo) you are effectively giving the name x to a new var in your namespace. It happens to have the same value as foo (i.e. it contains the same function) but is otherwise completely independent from foo. It's like having two references to the same object, to use a Java analogy.
Why should you continue to want to obtain the name foo?
If you really want to do something similar to this, this might be a case where you could use some custom metadata on the function which contains the original symbol:
(def foo
(with-meta
(fn [x] x)
{:original-function `foo}))
(def bar foo)
(defn original-function [v]
"Returns the :original-function symbol from the metadata map"
(:original-function (meta v)))
(original-function bar)
=> user/foo

Lisp defparameter use the name as arguments

I want to do that
(defparameter name (myfunct args))
In myfunct I need to reuse to assign to a variable the "name" that I use in the defparameter! Is it possible? How can I access to that from myfunct.
If I understand your question correctly, you want myfunc to know what `name' is. Here's how you would do that.
(defun myfunc (name arg1 arg2 ... argN)
(setf var name) ;;if this is what you want
... do things with args and name...)
Then do
(defparameter name (myfunc 'name args...))
However, if you want to do this sort of thing often, you might want to create a macro that will pass 'name for you.
Also, look up symbol-value if you want the value of a symbol (for example 'name)

Clojure: Assigning defrecord fields from Map

Following up on How to make a record from a sequence of values, how can you write a defrecord constructor call and assign the fields from a Map, leaving un-named fields nil?
(defrecord MyRecord [f1 f2 f3])
(assign-from-map MyRecord {:f1 "Huey" :f2 "Dewey"}) ; returns a new MyRecord
I imagine a macro could be written to do this.
You can simply merge the map into a record initialised with nils:
(merge (MyRecord. nil nil nil) {:f1 "Huey" :f2 "Dewey"})
Note that records are capable of holding values stored under extra keys in a map-like fashion.
The list of a record's fields can be obtained using reflection:
(defn static? [field]
(java.lang.reflect.Modifier/isStatic
(.getModifiers field)))
(defn get-record-field-names [record]
(->> record
.getDeclaredFields
(remove static?)
(map #(.getName %))
(remove #{"__meta" "__extmap"})))
The latter function returns a seq of strings:
user> (get-record-field-names MyRecord)
("f1" "f2" "f3")
__meta and __extmap are the fields used by Clojure records to hold metadata and to support the map functionality, respectively.
You could write something like
(defmacro empty-record [record]
(let [klass (Class/forName (name record))
field-count (count (get-record-field-names klass))]
`(new ~klass ~#(repeat field-count nil))))
and use it to create empty instances of record classes like so:
user> (empty-record user.MyRecord)
#:user.MyRecord{:f1 nil, :f2 nil, :f3 nil}
The fully qualified name is essential here. It's going to work as long as the record class has been declared by the time any empty-record forms referring to it are compiled.
If empty-record was written as a function instead, one could have it expect an actual class as an argument (avoiding the "fully qualified" problem -- you could name your class in whichever way is convenient in a given context), though at the cost of doing the reflection at runtime.
Clojure generates these days a map->RecordType function when a record is defined.
(defrecord Person [first-name last-name])
(def p1 (map->Person {:first-name "Rich" :last-name "Hickey"}))
The map is not required to define all fields in the record definition, in which case missing keys have a nil value in the result. The map is also allowed to contain extra fields that aren't part of the record definition.
As mentioned in the linked question responses, the code here shows how to create a defrecord2 macro to generate a constructor function that takes a map, as demonstrated here. Specifically of interest is the make-record-constructor macro.