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/
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've been trying for a while to solve this nREPL ticket and I'm out of ideas, so I decided to ask for a bit of help here.
Basically we need to be bind *print-namespace-maps* only if it's present or find some way to define if it's not present that doesn't mess up Clojure 1.9+.
Here are some of the things that don't work:
;; compilation error
(when (resolve '*print-namespace-maps*)
(set! *print-namespace-maps* (#bindings #'*print-namespace-maps*)))
;; shadows `clojure.core/*print-namespace-maps*` on 1.9, as the def gets executed always
(when-not (resolve 'clojure.core/*print-namespace-maps*)
(def ^:dynamic *print-namespace-maps*
"Define the var for clojure versions below 1.9"
nil))
Seems that dynamic vars can't be conditionally bound at all, which really sucks, but I guess there must be some way to do something like what we're aiming for.
Take a look at the linked issue for more details. Any help would be much appreciated!
I don't totally understand the details of the linked issue or nREPL impl., but the def behavior is a bit surprising here:
Clojure 1.8.0
user=> (when false (def ^:dynamic *foo* 1))
nil
I would've expected there to be no *foo* var after that evaluation, but it creates an unbound var:
user=> (var-get #'*foo*)
#object[clojure.lang.Var$Unbound 0x20da8800 "Unbound: #'user/*foo*"]
And I suppose that def compiler behavior is what causes the exception in 1.9 in your example:
WARNING: *print-namespace-maps* already refers to: #'clojure.core/*print-namespace-maps* in namespace: user, being replaced by: #'user/*print-namespace-maps*
Maybe a macro could be used so that the resolve check happens during macro expansion, and doesn't emit a def if it resolves:
(defmacro def-dynamic-when-not-resolve [sym value]
(when-not (resolve sym)
`(def ~(vary-meta sym assoc :dynamic true) ~value)))
It seems to work on Clojure 1.8:
Clojure 1.8.0
user=> (def-dynamic-when-not-resolve *print-namespace-maps* 'sure)
#'user/*print-namespace-maps*
user=> *print-namespace-maps*
sure
And on Clojure 1.9:
Clojure 1.9.0
user=> (def-dynamic-when-not-resolve *print-namespace-maps* 'sure)
nil
user=> *print-namespace-maps*
true
I would like to write out an EDN data file from Clojure as tagged literals. Although the clojure.edn API contains read and read-string, there are no writers. I'm familiar with the issue reported here. Based on that, it's my understanding that the pr and pr-str functions are what are meant to be used today.
I wanted to check with the StackOverflow community to see if something like the following would be considered the "correct" way to write out an EDN file:
(spit "friends.edn" (apply str
(interpose "\n\n"
[(pr-str (symbol "#address-book/person") {:name "Janet Wood"})
(pr-str (symbol "#address-book/person") {:name "Jack Tripper"})
(pr-str (symbol "#address-book/person") {:name "Chrissy Snow"})])))
If you are using EDN in production, how do you write out an EDN file? Similar to the above? Are there any issues I need to look out for?
Update
The Clojure Cookbook entry, "Emitting Records as EDN Values" contains a more thorough explanation of this issue and ways to handle it that result in valid EDN tags.
you should not need to generate the tags manually. If you use any of the clojure type definition mechanisms they will be created by the printer. defrecord is particularly convenient for this.
(ns address-book)
(defrecord person [name])
(def people [(person. "Janet Wood")
(person. "Jack Tripper")
(person. "Chrissy Snow")])
address-book> (pr-str people)
"[#address_book.person{:name \"Janet Wood\"}
#address_book.person{:name \"Jack Tripper\"}
#address_book.person{:name \"Chrissy Snow\"}]"
if you want them formatted more nicely you can combine with-out-str and clojure.pprint/pprint. Using Clojure types to create the tags also gives you reading of those tags for free.
address-book> (read-string (pr-str people))
[#address_book.person{:name "Janet Wood"}
#address_book.person{:name "Jack Tripper"}
#address_book.person{:name "Chrissy Snow"}]
address-book> (def read-people (read-string (pr-str people)))
#'address-book/read-people
address-book> (type (first read-people))
address_book.person
The only downside I see is that you lose some control over the way the tags look if you have -'s in your namespace because java classes can't contain these so they get converted to underscores.
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))
I am trying to find out how to access Javascript objects properties in ClojureScript. If I know in advance the name of the property, that is easy. To get foo.bar I just do
(.-bar foo)
Is there a way to access a property whose name is known only at runtime? I am looking for the equivalent of the JS syntax foo[dynamicBar]
You can use aget / aset to access properties known only at runtime.
;; Use clj->js to convert clj(s) map to javascript.
;; Note the #js {:bar 100} reader literal indicating a js map.
cljs.user> (def foo (clj->js {:bar 100}))
#js {:bar 100}
cljs.user> (.-bar foo)
100
cljs.user> (aget foo "bar")
100
cljs.user> (aset foo "baz" 200)
200
cljs.user> (.-baz foo)
200
Using string names may be also important in case when you want to take advantage of :optimizations :advanced compiler mode, but you don't have externs file covering your code.
See David Nolen's example using goog.object.get:
https://github.com/clojure/clojurescript/wiki/Dependencies#using-string-names
While aget works. This method was originally supposed to provide you access to array elements, not properties of js objects in general. goog.object's get method is a better way to communicate your intent.
Here are the implementations of both methods:
https://github.com/google/closure-library/blob/1b8a893271d790626b5cd652b922675c987f106d/closure/goog/object/object.js#L403
https://github.com/clojure/clojurescript/blob/d2d031605b1ad552077218c8f445868653c01744/src/main/clojure/cljs/core.cljc#L942
As you can see, (aget o key)generates javascript code o[key] directly, but goog.object.get calls a method which first checks if the key is present in o.