I want to split a big clojure-script into smaller ones. And it looks like this.
One:
(ns one
(:use [two :only (show)]))
(def status "WORKING")
Two:
(ns two
(:use [one :only (status)]))
(defn show [] (println status))
Result: Exception.
PS I understand that some some kind of recursive namespace constructing happens. I know only a sloppy half-solution, like defining without body before referncing to namespaces? Any suggestions?
+1 for the answer of ponzao. To elaborate a bit more: Cyclic dependencies of namespaces are often a sign, that you didn't get your abstractions and/or APIs right. Either you "mix" layers or things should just be in one namespace, because the really belong together.
If you want to just split one namespace into several files, this is also possible.
name/space.clj:
(ns name.space)
(declare status)
(load "space_one")
(load "space_two")
name/space_one.clj:
(in-ns 'name.space)
(defn show [] (println status))
name/space_two.clj:
(in-ns 'name.space)
(def status "WORKING")
You are constructing a cyclic dependency between two components, are you sure this is what you want? Why not have a third namespace containing their common functions?
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}
How can I define a new record that "inherits" the protocols from an existing type?
To make this question clear, I'll illustrate with extending Ubergraph, but Ubergraph is only an example; I'm looking for the general solution, not just a solution that works for Ubergraph. Suppose that I'd like to add a global attribute, graph-name, to Ubergraph. Ideally, I could do something like this:
(defrecord named-ubergraph [g graph-name])
(extend-type named-ubergraph
(all-the-protocols-supported-by ubergraph.core.Ubergraph)
(call-the-same-functions-replacing-first-argument-with '(this g))
Of course I could look at the Ubergraph source code and manually write all the forwarding functions, but as you can see here, Ubergraph satisfies many protocols and many protocol methods.
Writing so much boilerplate code doesn't sound very Clojurely, and it seems like a lot of work when all I want to do is add one eensy-weensy bit of data to an Ubergraph. What's a better way?
Please feel free to reconceptualize the question if you think I'm looking at this wrong.
extend-type extends existing types to given protocols.
If I understand you properly, you want to extend existing record to achieve some kind of inheritance.
AFAIK, there's no easy way to do this.
However, if all you want is to add another field, you can easily assoc additional field to an existing record instance:
(defprotocol Cost
(cost [this price-list]))
(defrecord Car [name speed]
Cost
(cost [this price-list] (price-list (:name this))))
(def my-car (->Car "bmw" 200))
(def price-list {"bmw" 100000})
(cost my-car price-list)
;;=> 100000
(-> my-car
(assoc :color "blue")
(cost price-list))
;;=> 100000
UPDATE:
I've also found this fantastic discussion on Clojure mailing list: defrecord with "inheritance": https://groups.google.com/forum/#!topic/clojure/mr-o9sRyiZ0
Let's say I'm doing a web app that exposes API to fetch and mutate data about cats.
I'm implementing my db layer using Korma, so there will be something like that:
(ns kittens.db
(:require [korma.core :refer :all]))
(defn fetch-cats [db]
(select cats-table ...))
(defn fetch-cat-by-id [db id]
(select cats-table
...
(where {:id id})))
(defn create-cat [db data]
(insert cats-table
...))
...
...
After I'm implementing API routes as follows:
(ns kittens.routes
(:require [compojure.core :refer [defroutes GET POST ...]]
[kittens.db :as db]))
(defroutes cats-routes
(GET "/cats" [...] (db/fetch-cats ...))
(GET "/cats/:id" [...] (db/fetch-cat-by-id ...))
(POST "/new-cat" [...] (db/create-cat ...)))
In such implementation routes module talks directly to db module, which seems kinda inflexible to me. Should there be something in between of them?
In my opinion you do not need anything else, this is good.
Such a setup is already plenty flexible.
Seeing as all looks good, here is some general advice as things grow:
Avoid putting logic route bodies.
If the body of a route starts to grow, consider extracting it to a function.
Routes are less fun to test.
Colocate your routes and handler middleware unless you have so many routes they need to be split out into contexts.
Make sure your handler references the routes var #' not the routes directly so that reloading routes will work.
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 tried to follow the documentation for clojure.instant/read-instant-timestamp, which reads:
clojure.instant/read-instant-timestamp
To read an instant as a java.sql.Timestamp, bind *data-readers* to a
map with this var as the value for the 'inst key. Timestamp preserves
fractional seconds with nanosecond precision. The timezone offset will
be used to convert into UTC.`
The following result was unexpected:
(do
(require '[clojure.edn :as edn])
(require '[clojure.instant :refer [read-instant-timestamp]])
(let [instant "#inst \"1970-01-01T00:00:09.999-00:00\""
reader-map {'inst #'read-instant-timestamp}]
;; This binding is not appearing to do anything.
(binding [*data-readers* reader-map]
;; prints java.util.Date -- unexpected
(->> instant edn/read-string class println)
;; prints java.sql.Timestamp -- as desired
(->> instant (edn/read-string {:readers reader-map}) class println))))
How can I use the *data-readers* binding? Clojure version 1.5.1.
clojure.edn functions by default only use data readers stored in clojure.core/default-data-readers which, as of Clojure 1.5.1, provides readers for instant and UUID literals. If you want to use custom readers, you can do that by passing in a :readers option; in particular, you can pass in *data-readers*. This is documented in the docstring for clojure.edn/read (the docstring for clojure.edn/read-string refers to that for read).
Here are some examples:
(require '[clojure.edn :as edn])
;; instant literals work out of the box:
(edn/read-string "#inst \"2013-06-08T01:00:00Z\"")
;= #inst "2013-06-08T01:00:00.000-00:00"
;; custom literals can be passed in in the opts map:
(edn/read-string {:readers {'foo identity}} "#foo :asdf")
;= :asdf
;; use current binding of *data-readers*
(edn/read-string {:readers *data-readers*} "...")
(The following section added in response to comments made by Richard Möhn in this GitHub issue's comment thread. The immediate question there is whether it is appropriate for a reader function to call eval on the data passed in. I am not affiliated with the project in question; please see the ticket for details, as well as Richard's comments on the present answer.)
It is worth adding that *data-readers* is implicitly populated from any data_readers.{clj,cljc} files that Clojure finds at the root of the classpath at startup time. This can be convenient (it allows one to use custom tagged literals in Clojure source code and at the REPL), but it does mean that new data readers may appear in there with a change to a single dependency. Using an explicitly constructed reader map with clojure.edn is a simple way to avoid surprises (which could be particularly nasty when dealing with untrusted input).
(Note that the implicit loading process does not result in any code being loaded immediately, or even when a tag mentioned in *data-readers* is first encountered; the process which populates *data-readers* creates empty namespaces with unbound Vars as placeholders, and to actually use those readers one still has to require the relevant namespaces in user code.)
The *data-readers* dynamic var seems to apply to the read-string and read functions from clojure.core only.
(require '[clojure.instant :refer [read-instant-timestamp]])
(let [instant "#inst \"1970-01-01T00:00:09.999-00:00\""
reader-map {'inst #'read-instant-timestamp}]
;; This will read a java.util.Date
(->> instant read-string class println)
;; This will read a java.sql.Timestamp
(binding [*data-readers* reader-map]
(->> instant read-string class println)))
Browsing through the source code for clojure.edn reader here, I couldn't find anything that would indicate that the same *data-readers* var is used at all there.
clojure.core's functions read and read-string use LispReader (which uses the value from *data-readers*), while the functions from clojure.edn use the EdnReader.
This edn library is relatively new in Clojure so that might be the reason why the documentation string is not specific enough regarding edn vs. core reader, which can cause this kind of confusion.
Hope it helps.