So I think clojure.core/bean is pretty close to what I want, but I'm working with a Java application that has nested beans, such that I end up with maps like this:
{:month-total 3835.0 :name "Jan's Meat Diner" :owners #<BarOwner[] [Lcom.fancypants.BarOwner;#1fb332d}
How, do I call bean recursively on a Java object so that I can get my imaginary BarOwner object to emit itself as a map, too:
{:month-total 3835.0 :name "Jan's Meat Diner" :owners { [:name "Jack"] [:name "Jill"] } }
Edit 1
I have found that clojure/java.data and from-java is probably a better fit for this kind of thing than bean.
Although it's probably not an ideal answer to "how to use bean recursively", using more of the richer contrib libraries under the Clojure community's site did solve it. Specifically
clojure/java.data
provides simple recursive bean resolving, and can be configured to handle java types specifically in the hairy cases. I'd recommend this to other people who want to use bean.
It is very tricky to find out what is a bean and what is not. This seems to do the trick for beans inside beans and properties that are lists. Probably you will want to add more classes to the probably-bean? function and perhaps some support for properties that are maps.
(defn probably-bean? [o]
(and (not (coll? o))
((complement #{Class Long String clojure.lang.Keyword}) (class o))))
(defn transf [o]
(cond
(instance? java.util.List o) (into [] (map transf o))
(probably-bean? o) (into {} (seq (bean o)))
:else o))
(defn to-bean [o]
(clojure.walk/prewalk #(transf %) o))
Related
If I've been playing around in a clojure REPL (might have been experimenting with (assoc) or (seq) or (reduce) and created some temporary maps for examples), but wanted to print a listing of variables defined in that session, is there a way to do this? Something like (println def) or something?
You can use (dir user) if you are in the user namespace. Or any other ns you are interested into. This shows you all the def-ed things. If it's not there (it usually gets useed automatically in the REPL, you can find it in clojure.repl/dir).
ns-interns can get you pretty close I think.
user=> (def x 1)
#'user/x
user=> (def y 2)
#'user/y
user=> (ns-interns *ns*)
{x #'user/x, y #'user/y}
I am new to Clojure and Reagent. Kindly tell how to print the variable first inside the atom variable contacts?
(def app-state
(r/atom
{:contacts [{:first "Ben" :last "Lem" :middle "Ab"}]}))
First of all: the reagent tutorial is a really good place to start. It even gives you examples to solve exactly this problem.
Since reagents atom can be treated just as a regular Clojurescript atom, you can use all your normal sequence operations. Keep in mind that in order to access the current value, you have to dereference the atom via #.If you really just want to access the first :first in your atom:
(:first (first (:contacts #app-state))) or (get (first (get #app-state :contacts)) :first)
Or, if you think it's more readable
(-> #app-state
:contacts
first
:first)
I guess what you might want to do is define a few functions to make the access more easy such as:
(defn get-contacts!
"Returns the current vector of contacts stored in the app-state."
[]
(:contacts #app-state))
(defn get-first-names!
"Return a vector of all first names in the current list of contacts in the
app-state."
[]
(mapv :first (get-contacts!)))
Please keep in mind that in reagent (and in general really) you might want to dereference that atom as fiew times as possible, so look for a good place to dereference it and just use regular functions that operate on a simple sequence instead of an atom.
Still, I would really suggest you go read the aforementioned reagent tutorial.
Here is a concise way to access the value that you are looking for using Clojure's (get-in m ks) function:
(get-in #app-state [:contacts 0 :first])
Just as an extra, you may see this often written as
(->> #app-state
:contacts
(mapv :first)
first
and it's useful to understand what's going on here.
->> is a macro called thread-last which will re-write the code above to be
(first (mapv :first (:contacts #app-state)))
Thread last is a bit weird at first but it makes the code more readable when lots of things are going on. I suggest that on top of the reagent tutorial mentioned in the other comments, you read this.
#app-state will give you whatever is inside the r/atom and (:first (first (:contacts #app-state))) will return the first element and (println (:first (first (:contacts #app-state)))) will print output to the browser console (so you need to have the developer tools console open to see it).
Note that for println to output to the browser developer tools console you need to have this line in your code:
(enable-console-print!)
I am learning Clojure and using Clojure 1.5.1. It seems Clojure 1.5.1 no longer has the defnk macro. So, what is the equivalent for defnk in Clojure 1.5.1 ?
defnk once resided in clojure-contrib, but didn't make the jump into a new package when clojure-contrib was splitted up into multiple packages.
Instead of defnk you could use :keys/:or yourself to create default values for your function arguments, so
(defnk f [:b 43] (inc b))
becomes
(defn f [& {:keys [b] :or {b 1}}] (inc b))
If you don't like it this way, nothing stops you from taking the source of defnk and use it yourself.
I'm developing a web application with Clojure, currently with Ring, Moustache, Sandbar and Hiccup. I have a resource named job, and a route to show a particular step in a multi-step form for a particular job defined like this (other routes omitted for simplicity):
(def web-app
(moustache/app
;; matches things like "/job/32/foo/bar"
:get [["job" id & step]
(fn [req] (web.controllers.job/show-job id step))]))
In the view my controller renders, there are links to other steps within the same job. At the moment, these urls are constructed by hand, e.g. (str "/job/" id step). I don't like that hard-coded "/job/" part of the url, because it repeats what I defined in the moustache route; if I change the route I need to change my controller, which is a tighter coupling than I care for.
I know that Rails' routing system has methods to generate urls from parameters, and I wish I had similar functionality, i.e. I wish I had a function url-for that I could call like this:
(url-for :job 32 "foo" "bar")
; => "/job/32/foo/bar"
Is there a Clojure web framework that makes this easy? If not, what are your thoughts on how this could be implemented?
Noir provides something similar. It's even called url-for.
The example function you have mentioned could be implemented as below. But I am not sure if this is exactly what you are looking for.
(defn url-for [& rest]
(reduce
#(str %1 "/" %2) "" (map #(if (keyword? %1) (name %1) (str %1)) rest)))
I am trying to understand how Clojure hierarchies work, with the derive and is-a? constructs. I'm not sure how I would use these with the maps and records in my program. Has anyone used these?
I find your question a bit vague. Have you read the documentation on the Clojure website?
http://clojure.org/multimethods
I find the examples there quite easy to follow:
user=> ::rect
:user/rect
user=> (derive ::rect ::shape)
nil
user=> (parents ::rect)
#{:user/shape}
user=> (derive ::square ::rect)
nil
user=> (ancestors ::square)
#{:user/shape :user/rect}
user=> (isa? ::square ::shape)
true
There's also this blog post with a more "real-world" example:
http://www.prodevtips.com/2010/06/20/clojure-inheritance/