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]))))
Related
Is there a Common Lisp construct that is to labels what defmethod is to defun? That is, I would like to use labels (or something similar) to define several local functions that would have the same name but differ in parameters they accept and let the compiler choose among them.
As an MWE, I would like to achieve the following functionality
(defmethod write-first-item-type ((lst list))
"Writes the type of the first item in lst."
(labels ((write-single ()
(format t "a single float"))
(write-double ()
(format t "a double float")))
(format t "The first item is: ~A.~%"
(cond ((eql (type-of (car lst)) 'single-float)
(write-single))
((eql (type-of (car lst)) 'double-float)
(write-double))
(t
(format t "unknown"))))))
with something like
(defmethod write-first-item-type ((lst list))
"Should write the type of the first item in lst but does not compile."
(label-method ((write-type ((item single-float))
(format t "a single float"))
(write-type ((ifem double-float))
(format t "a double float")))
(format t "The first item is: ~A.~%"
(write-type (car lst)))))
Admitably, my MWE is rather silly. My actual motivation is that while cleaning up my source code I would like to put bunches of little helper functions (created with defmethod) into the one big function that uses them. Feel free to comment on this motivation as well!
See here why the initial proposal for local generic bindings were removed from CLOS:
Issue GENERIC-FLET-POORLY-DESIGNED Writeup
I am not aware of a built-in functionality of that kind. However, such kind of feature is not hard to build from scratch, as long as other parts of OOP are not required (i.e., inheritance and other dispatching orders).
If you would never call (call-next-method) in you method-labels code (as you won't do in labels code, it is just a matter of defining a dispatch table and dispatch "methods" accordingly. To break it down, it should be a local macro that:
defines a local variable (gensym) as the dispatch table;
registers functions as closures together with its specialized lambda list into the dispatch table;
register a local "generic" function, that when called, find the function to call from the dispatch table according to the parameters supplied.
And to find the function, you may or may not need to:
sort the dispatch table (but if there is not eql specifier nor inheritance, this can be avoided)
write dedicated code to match against the specialized parameters for &optional, &key, and other options of the lambda list (or you can use destructuring-bind, but you'll need to transform the specialized lambda list into a lambda list) - there might be tools for that, but I am unaware of.
In the simplest case where the number of parameters in the lambda list is fixed, the dispatch can be as plain as a few (e)typecase.
The local/global methods are for you probably a matter of namespaces.
That you don't want to pollute the current namespace with this matter.
How about to create on-the-fly small namespace/packages and use therein the "global" methods of CLOS?
It would have nearly the same effect of having local functions which are "invisible" for other functions.
(defpackage my-sub
(:use :cl)
(:export #:write-type))
(in-package :my-sub)
(defgeneric write-type (x)
(:documentation "write type of x"))
(defmethod write-type ((x float))
(typecase x
(single-float "single float")
(double-float "double float")))
(defmethod write-type ((x string))
"string")
(defpackage my-main
(:use :cl
:my-sub))
(in-package :my-main)
(defmethod write-first-item-type ((lst list))
(format nil "first item is: ~A." (my-sub:write-type (car lst))))
(write-first-item-type '("a" b c))
;; "first item is: string."
(write-first-item-type '(1.0 2 3))
;; "first item is: single float."
(write-first-item-type '(1.0d0 2 3))
;; "first item is: double float."
defmethod anyway can only dispatch for classes - builtin or self-made.
But you want to dispatch for types.
So I put example for members of class float (single-float and double-float) - dispatch them manually useing typecase.
And of built-in class string.
Use packaging for namespace separation.
However just manual dispatch is better in this case.
(defmethod write-first-item-type ((lst list))
(labels ((write-type (x)
(typecase x
(single-float "single float")
(double-float "double float")
(string "string")
(t "unkown"))))
(format nil "The first item is: ~A." (write-type (car lst)))))
I'm new to Clojure, after trying multiple methods I'm completely stuck. I know how to achieve this in any other imperative languages, but not in Clojure.
I have a JSON file https://data.nasa.gov/resource/y77d-th95.json containing meteor fall data, each fall includes a mass and year.
I'm trying to find which year had the greatest collective total mass of falls.
Here's what I have so far:
(def jsondata
(json/read-str (slurp "https://data.nasa.gov/resource/y77d-th95.json") :key-fn keyword))
;Get the unique years
(def years (distinct (map :year jsondata)))
;Create map of unique years with a number to hold the total mass
(def yearcount (zipmap years (repeat (count years) 0)))
My idea was to use a for function to iterate through the jsondata, and update the yearcount map with the corresponding key (year in the fall object) with the mass of the object (increment it by, as in += in C)
I tried this although I knew it probably wouldn't work:
(for [x jsondata]
(update yearcount (get x :year) (+ (get yearcount (get x :year)) (Integer/parseInt (get x :mass)))))
The idea of course being that the yearcount map would hold the totals for each year, on which I could then use frequencies, sort-by, and last to get the year with the highest mass.
Also defined this function to update values in a map with a function, although Im not sure if I could actually use this:
(defn map-kv [m f]
(reduce-kv #(assoc %1 %2 (f %3)) {} m))
I've tried a few different methods, had lots of issues and just can't get anywhere.
Here's an alternate version just to show an approach with a slightly different style. Especially if you're new to clojure it may be easier to see the stepwise thinking that led to the solution.
The tricky part might be the for statement, which is another nice way to build up a new collection by (in this case) applying functions to each key and value in an existing map.
(defn max-meteor-year [f]
(let [rdr (io/reader f)
all-data (json/read rdr :key-fn keyword)
clean-data (filter #(and (:year %) (:mass %)) all-data)
grouped-data (group-by #(:year %) clean-data)
reduced-data
(for [[k v] grouped-data]
[(subs k 0 4) (reduce + (map #(Double/parseDouble (:mass %)) v))])]
(apply max-key second reduced-data)))
clj.meteor> (max-meteor-year "meteor.json")
["1947" 2.303023E7]
Here is my solution. I think you'll like it because its parts are decoupled and are not joined into a single treading macro. So you may change and test any part of it when something goes wrong.
Fetch the data:
(def jsondata
(json/parse-string
(slurp "https://data.nasa.gov/resource/y77d-th95.json")
true))
Pay attention, you may just pass true flag that indicates the keys should be keywords rather than strings.
Declare a helper function that takes into account a case when the first argument is missing (is nil):
(defn add [a b]
(+ (or a 0) b))
Declare a reduce function that takes a result and an item from a collection of meteor data. It updates the result map with our add function we created before. Please note, some items do not have either mass or year keys; we should check them for existence before operate on them:
(defn process [acc {:keys [year mass]}]
(if (and year mass)
(update acc year add (Double/parseDouble mass))
acc))
The final step is to run reducing algorithm:
(reduce process {} jsondata)
The result is:
{"1963-01-01T00:00:00.000" 58946.1,
"1871-01-01T00:00:00.000" 21133.0,
"1877-01-01T00:00:00.000" 89810.0,
"1926-01-01T00:00:00.000" 16437.0,
"1866-01-01T00:00:00.000" 559772.0,
"1863-01-01T00:00:00.000" 33710.0,
"1882-01-01T00:00:00.000" 314462.0,
"1949-01-01T00:00:00.000" 215078.0,
I think that such a step-by-step solution is much more clearer and maintainable than a single huge ->> thread.
Update: sorry, I misunderstood the question. I think this will work for you:
(->> (group-by :year jsondata)
(reduce-kv (fn [acc year recs]
(let [sum-mass (->> (keep :mass recs)
(map #(Double/parseDouble %))
(reduce +))]
(assoc acc year sum-mass)))
{})
(sort-by second)
(last))
=> ["1947-01-01T00:00:00.000" 2.303023E7]
The reduce function here is starting out with an initial empty map, and its input will be the output of group-by which is a map from years to their corresponding records.
For each step of reduce, the reducing function is receiving the acc map we're building up, the current year key, and the corresponding collection of recs for that year. Then we get all the :mass values from recs (using keep instead of map because not all recs have a mass value apparently). Then we map over that with Double/parseDouble to parse the mass strings into numbers. Then we reduce over that to sum all the masses for all the recs. Finally we assoc the year key to acc with the sum-mass. This outputs a map from years to their mass sums.
Then we can sort those map key/value pairs by their value (second returns the value), then we take the last item with the highest value.
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)
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
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