Calling `(get-thread-binding)` results in a stack overflow - clojure

When I run
user> (get-thread-bindings)
I see
StackOverflowError clojure.lang.PersistentHashMap$BitmapIndexedNode.index (PersistentHashMap.java:677)
This is with a fresh lein new foo project, where I have a single line
(def foo "Hello World")
The stack trace has repeated calls to clojure.core/pr-on and clojure.core/print-map, etc. but the initial call that triggered this isn't visible.

Whenever you evaluate expressions in the REPL, the results of the three most recent expressions are stored in special thread-bound vars named *1, *2, and *3. Those vars are included in the map returned by get-thread-bindings, because they are thread-bound. In particular, *1 is a map of all thread-bound vars, one of whose values is the var *1 again.
It's okay for such a circular reference to exist in memory, but when you try to print it to the REPL, you will have trouble, because it looks like an infinitely deep tree. Instead, if you want to look around at the map returned by (get-thread-bindings), you will have to be a little bit more careful to only look at parts of it which are not infinite. For example, here's what I did to double-check that my answer to your question was correct:
user=> (class (get-thread-bindings))
clojure.lang.PersistentHashMap
user=> (keys (get-thread-bindings))
(#<Var: --unnamed--> #<Var: --unnamed--> #'clojure.core/*assert* #'clojure.core/*compile-path* #'clojure.core/*math-context* #'clojure.test/*test-out* #'clojure.core/*out* #<Var: --unnamed--> #'clojure.core/*2 #'clojure.core/*source-path* #'clojure.core/*err* #'clojure.core/*data-readers* #<Var: --unnamed--> #'clojure.core/*command-line-args* #<Var: --unnamed--> #'clojure.core/*warn-on-reflection* #'clojure.tools.nrepl.middleware.interruptible-eval/*msg* #'clojure.core/*read-eval* #'clojure.core/*default-data-reader-fn* #'clojure.core/*1 #'clojure.core/*unchecked-math* #'clojure.core/*e #'clojure.core/*file* #'clojure.core/*print-length* #'clojure.core/*3 #<Var: --unnamed--> #<Var: --unnamed--> #<Var: --unnamed--> #'clojure.core/*ns* #'clojure.core/*print-level* #<Var: --unnamed--> #<Var: --unnamed--> #<Var: --unnamed--> #'clojure.core/*in* #'clojure.core/*print-meta* #'clojure.tools.nrepl.middleware.session/*out-limit*)
user=> (map (comp :name meta) (keys (get-thread-bindings)))
(nil nil *assert* *compile-path* *math-context* *test-out* *out* nil *2 *source-path* *err* *data-readers* nil *command-line-args* nil *warn-on-reflection* *msg* *read-eval* *default-data-reader-fn* *1 *unchecked-math* *e *file* *print-length* *3 nil nil nil *ns* *print-level* nil nil nil *in* *print-meta* *out-limit*)
Circular structures are a bit of a pain in a data-oriented language like Clojure, because you're used to being able to print anything to see what it's all about, and you can't print these. But you can still investigate them, as I did above, by seeing what class they are, and then investigating them in some way that works with that class (eg, for a map, looking at its keys is typically a good idea).
Supposing that Stack Overflow didn't exist, or you were stuck on a space station with no Internet access, how could you have discovered the *1 phenomenon yourself? Once you saw that it was impossible to print all of get-thread-bindings, you could have discovered that it was a map, and then looked around at its keys to see which of them explode when you print them and which don't. Then you could look further into the explosive one (*1), and discovered that it was another map, which contained another key named *1 whose value was another map...Hopefully this gives you some idea of how to debug similar issues in the future.

Related

Extend swap! behaviour for nil type in Clojure

let suppose, I have var atom-var
(def atom-val (atom []))
Also suppose a standard behaviour of atom:
(swap! atom-val conj {:b "2"})
=> #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}]
(#atom-val)
=> #object[clojure.lang.Atom 0x6500d3fd {:status :ready, :val [{:a "2"}]
I want to create the same behaviour as it would work with nil object, but without actions:
(def atom-val nil)
(swap! atom-val conj "New val")
Of course, I will get a NullPointerException. But I want that nothing happened, supress it. I do not need to write try every time it, I just need the described behavuiour.
I see that swap! is a function, atom is a function, atom returns clojure.lang.IAtom, clojure.lang.IAtom is an interface. I cannot extend interface.
How can I get the described behaviour?
Well, I have a global dynamic variable which is equal to nil
(def ^:dynamic atom-val nil).
Whenever a thread is created (it's ring handler with compojure), I am binding atom-val to
(defn func [handler]
(fn [request]
(binding [atom-val (atom [])]
(handler request)
)
)
So, I have such a form in different functions:
(swap! atom-val conj "New val").
I can run it everywhere lots of times (inside/outside different functions). It's really bad to check every time whether atom-val is null or not. Functions have to make swap!, but sometimes atom-val cannot be initialized properly (when a function makes swap! outside ring handlers, before binding).
So I decided to do it this way: I'd like to extend swap! protocol for Atom and when nil (when atom-val is nil) is passed it mustn't throw NullPointerException.
If you want an atom that does nothing, you can write:
(def noop-atom
(reify clojure.lang.IAtom
(reset [_ _])
(swap [_ _])
(swap [_ _ _])
(swap [_ _ _ _])
(swap [_ _ _ _ _])
(compareAndSet [_ _ _])))
You can then use this atom as the root-value of the dynamic var.
If your goal is to manage state during the lifecycle of a Ring request/response, you can write a custom middleware.
You need to use fnil. See https://clojuredocs.org/clojure.core/fnil
Example:
(def atom-val nil)
(def nil-swap! (fnil swap! (atom [])))
(nil-swap! atom-val conj "New val") => ["New val"]
And don't forget to keep a browser tab open to The Clojure CheatSheet at all times!
So, you want to swap! on a nil? I'm not sure what you meant with actions and doing nothing.
It definitely doesn't make sense (at least to me) to swap! a nil value; if it does to you, you should review what atoms really are. Perhaps you mean that when given a nil instead of an atom reference the swap! wouldn't do anything.
If so then you can just make your own function to do that check for you:
(defn nilable-swap!
[a f]
(when a (swap! a f)))
But I really don't recommend you do that, if this is what you want to do, it's an indication of bad design and control flow. Of course, it does make sense to check if your atom reference is nil if you're not sure, but do you really need to routinely check that? is there truly no point in which you know you got your atom reference?
I think I might have answered your question but if I misunderstood, feel free to clarify and I'll update/delete the answer.

How can I iterate over a list with a macro?

I am trying to print the documentation for all functions in a given namespace by invoking the following expression in a REPL:
(doseq
[f (dir-fn 'clojure.repl)]
(doc f))
However the invocation of this expression returns nil without printing the documentation to the REPL. I know this might have to do with doc being a macro, but I'm a Clojure novice and am not entirely sure how to understand the problem.
Why does this expression return nil without printing the documentation?
How can this expression be modified so that it prints the documentation for each function in a given namespace?
Thanks!
Update: Combined both provided answers:
(defn ns-docs [ns']
(doseq [[symbol var] (ns-interns ns')]
(newline)
(println symbol)
(print " ")
(println (:doc (meta var)))))
(ns-docs 'clojure.repl)
I would, instead, start here:
The Clojure CheatSheet
ClojureDocs.org
Clojure-Doc.org (similar name, but different)
The API & Reference sections at Clojure.org
Note that doc is in the namespace clojure.repl, which reflects its intended usage (by a human in a repl). Here is some code that will also iterate on a namespace & print doc strings (using a different technique):
(doseq [[fn-symbol fn-var] (ns-interns 'demo.core)]
(newline)
(println fn-symbol)
(println (:doc (meta fn-var))))
where demo.core is the namespace of interest.
Note that ns-interns gives you both a symbol and var like:
fn-symbol => <#clojure.lang.Symbol -main>
fn-var => <#clojure.lang.Var #'demo.core/-main>
The meta function has lots of other info you may want to use someday:
(meta fn-var) =>
<#clojure.lang.PersistentArrayMap
{ :arglists ([& args]),
:doc "The Main Man!",
:line 9, :column 1,
:file "demo/core.clj",
:name -main,
:ns #object[clojure.lang.Namespace 0x14c35a06 "demo.core"]}>
While this probably won't help you with answering your question, the problem of evaluating macro's comes up a lot when you are learning Clojure.
Macros are responsible for the evaluation of their arguments. In this case clojure.repl/doc will ignore the current lexical context and assume that the symbol f that you're giving it is the name of a function you want to see the documentation for. It does this because it's intended to be used at the REPL, and is assuming you wouldn't want to type quotes all the time.
As f doesn't exist, it prints nothing. Then doseq returns nil, since it exists to do something for side effects only - hence starting in do. In order to pass an argument to a macro that refuses to respect the lexical context like this, you need to write the code for each element in the list.
You can do this by hand, or by constructing the code as data, and passing it to eval to execute. You can do this in an imperative style, using doseq:
(doseq [f (ns-interns 'clojure.repl)]
(eval `(doc ~(symbol "clojure.repl" (str (first f))))))
or in a slightly more Clojurey way (which will allow you to see the code that it would execute by removing eval from the end and running it at the REPL):
(->> (ns-interns 'clojure.repl)
(map #(list 'clojure.repl/doc (symbol "clojure.repl" (str (first %)))))
(cons `do)
eval)
In both of these we use quote and syntax-quote to construct some code from the list of symbols reflected from the namespace, and pass it to eval to actually execute it. This page on Clojure's weird characters should point you in the right direction for understanding what's going on here.
This an example of why you shouldn't write macro's, unless you've got no other options. Macro's do not compose, and are often difficult to work with. For a more in depth discussion, Fogus's talk and Christophe Grand's talk are both good talks.
Why does this expression return nil without printing the documentation?
Because the doc macro is receiving the symbol f from your loop, instead of a function symbol directly.
How can this expression be modified so that it prints the documentation for each function in a given namespace?
(defn ns-docs [ns']
(let [metas (->> (ns-interns ns') (vals) (map meta) (sort-by :name))]
(for [m metas :when (:doc m)] ;; you could filter here if you want fns only
(select-keys m [:name :doc]))))
(ns-docs 'clojure.repl)
=>
({:name apropos,
:doc "Given a regular expression or stringable thing, return a seq of all
public definitions in all currently-loaded namespaces that match the
str-or-pattern."}
...
)
Then you can print those maps/strings if you want.

Clojure Spec Not Validating Data Properly

I am super confused by Clojure Spec. When I run in the repl by entering:
(require '[clojure.spec.alpha :as s])
And then add:
(s/valid? even? 10)
I get //true. And when I run:
(s/valid? even? 11)
//False. Ok so that works. Then when I require spec in my core.clj as:
(ns spam-problem.core
(:require [clojure.spec.alpha :as s]
[clojure.spec.gen.alpha :as gen]))
And try a simple validation to get it to throw an error, nothing happens:
(defn -main
"I don't do a whole lot ... yet."
[& args]
(s/valid? even? 11))
I have no idea what I'm doing wrong here and am very confused about how spec is supposed to work. I am running this by using command lein run. Is there another way you're supposed to run it?
I understand what you are feeling because once I got into Spec it caused me the same thoughts. What really helped me to solve the problem in my mind is to considering Spec being not a final library but rather a framework. In my projects, usually I've got a special module with high-level wrappers above basic spec capabilities. I believe, you might do the same: define a function that takes data, spec and raises those error message you desire to have in terms of your business-logic. Here is a small example of my code:
(ns project.spec
(:require [clojure.spec.alpha :as s]))
;; it's better to define that value is a constant
(def invalid :clojure.spec.alpha/invalid)
(defn validate
"Either returns coerced data or nil in case of error."
[spec value]
(let [result (s/conform spec value)]
(if (= result invalid)
nil
result)))
(defn spec-error
"Returns an error map for data structure that does not fit spec."
[spec data]
(s/explain-data spec data))
Now, let's prepare some specs:
(defn x-integer? [x]
(if (integer? x)
x
(if (string? x)
(try
(Integer/parseInt x)
(catch Exception e
invalid))
invalid)))
(def ->int (s/conformer x-integer?))
(s/def :opt.visits/fromDate ->int)
(s/def :opt.visits/toDate ->int)
(s/def :opt.visits/country string?)
(s/def :opt.visits/toDistance ->int)
(s/def :opt.visits/params
(s/keys :opt-un [:opt.visits/fromDate
:opt.visits/toDate
:opt.visits/country
:opt.visits/toDistance]))
And here are some usage examples:
(let [spec :opt.visits/params
data {:some :map :goes :here}]
(if-let [cleaned-data (validate spec data)]
;; cleaned-data has values coerced from strings to integers,
;; quite useful for POST parameters
(positive-logic cleaned-data)
;; error values holds a map that describes an error
(let [error (spec-error spec data)]
(error-logic-goes-here error))))
What might be improved here is to have a combo-function with both validate and error functionality. Such a function could return a vector of two values: success flag and either result or error data structure as follows:
[true {:foo 42}] ;; good result
[false {:error :map}] ;; bad result
The Spec library does not dictate a single way of processing data; that's why it's really good and flexible.
valid? is a predicate that returns true or false. Your program isn’t doing anything with the return value. Try printing it to console or using s/assert if you want to throw an exception:
If (check-asserts?) is false at runtime, always returns x. Defaults to
value of 'clojure.spec.check-asserts' system property, or false if not
set. You can toggle check-asserts? with (check-asserts bool).
So you may need to set (s/check-asserts true) to have s/assert throw exceptions:
(clojure.spec.alpha/assert even? 3)
=> 3
(clojure.spec.alpha/check-asserts?)
=> false
(clojure.spec.alpha/check-asserts true)
=> true
(clojure.spec.alpha/assert even? 3)
ExceptionInfo Spec assertion failed
val: 3 fails predicate: :clojure.spec.alpha/unknown
clojure.core/ex-info (core.clj:4739)

Clojure: Dynamically create functions from a map -- Time for a Macro?

I have a function that begins like this:
(defn data-one [suser]
(def suser-first-name
(select db/firstNames
(fields :firstname)
(where {:username suser})))
(def suser-middle-name
(select db/middleNames
(fields :middlename)
(where {:username suser})))
(def suser-last-name
(select db/middleNames
(fields :lastname)
(where {:username suser})))
;; And it just continues on and on...
)
Of course, I don't like this at all. I have this pattern repeating in many areas in my code-base and I'd like to generalize this.
So, I came up with the following to start:
(def data-input {:one '[suser-first-name db/firstNames :firstname]
'[suser-middle-name db/middleNames :middlename]
'[suser-last-name db/lastNames :lastname]})
(defpartial data-build [data-item suser]
;; data-item takes the arg :one in this case
`(def (data-input data-item)
(select (data-input data-item)
(fields (data-input data-item))
(where {:username suser}))))
There's really a few questions here:
-- How can I deconstruct the data-input so that it creates x functions when x is unknown, ie. that the values of :one is unknown, and that the quantities of keys in data-input is unknown.
-- I'm thinking that this is a time to create a macro, but I've never built one before, so I am hesitant on the idea.
And to give a little context, the functions must return values to be deconstructed, but I think once I get this piece solved, generalizing all of this will be doable:
(defpage "/page-one" []
(let [suser (sesh/get :username)]
(data-one suser)
[:p "Firat Name: "
[:i (let [[{fname :firstname}] suser-first-name]
(format "%s" fname))]
[:p "Middle Name: "
[:i (let [[{mname :emptype}] suser-middle-name]
(format "%s" mname))]
[:p "Last Name: "
[:i (let [[{lname :months}] suser-last-name]
(format "%s" lname))]]))
Some suggestions:
def inside a function is really nasty - you are altering the global environment, and it can cause all kinds of issues with concurrency. I would suggest storing the results in a map instead.
You don't need a macro here - all of the data fetches can be done relatively easily within a function
I would therefore suggest something like:
(def data-input [[:suser-first-name db/firstNames :firstname]
[:suser-middle-name db/middleNames :middlename]
[:suser-last-name db/lastNames :lastname]])
(def data-build [data-input suser]
(loop [output {}
items (seq data-input)]
(if items
(recur
(let [[kw db fieldname] (first items)]
(assoc output kw (select db (fields fieldname) (where {:username suser}))))
(next items))
output)))
Not tested as I don't have your database setup - but hopefully that gives you an idea of how to do this without either macros or mutable globals!
Nice question. First of all here's the macro that you asked for:
(defmacro defquery [fname table fields ]
(let [arg-name (symbol 'user-name)
fname (symbol fname)]
`(defn ~fname [~arg-name]
(print ~arg-name (str ~# fields)))))
You can call it like that:
(defquery suser-first-name db/firstNames [:firstname])
or if you prefer to keep all your configurations in a map, then it will accept string as the first argument instead of a symbol:
(defquery "suser-first-name" db/firstNames [:firstname])
Now, if you don't mind me recommending another solution, I would probably chose to use a single function closed around configuration. Something like that:
(defn make-reader [query-configurations]
(fn [query-type user-name]
(let [{table :table field-names :fields}
(get query-configurations query-type)]
(select table
(apply fields field-names)
(where {:username suser})))))
(def data-input {:firstname {:table db/firstNames :fields :firstname}
:middlename {:table db/middleNames :fields :middlename}
:lastname {:table db/lastNames :fields :lastname}})
(def query-function (make-reader data-input))
;; Example of executing a query
(query-function :firstname "tom")
By the way there's another way to use Korma:
;; This creates a template select from the table
(def table-select (select* db/firstNames))
;; This creates new select query for a specific field
(def first-name-select (fields table-select :firstname))
;; Creating yet another query that filters results by :username
(defn mkselect-for-user [suser query]
(where query {:username suser}))
;; Running the query for username "tom"
;; I fully specified exec function name only to show where it comes from.
(korma.core/exec (mkselect-for-user "tom" first-name-select))
For more information I highly recommend looking at Korma sources.

Distinguishing a record instance from a map

I'm trying to call clojure.walk/stringify-keys on a map that might include record instances. Since stringify-keys is recursive, it attempts to convert the keys on my record, (since (map? record-var) is true) which causes an error. Is there any way to tell if a var is a record rather than just a Clojure map? I
d like to provide my own implementation of stringify-keys that is record-aware.
The current implementation of stringify-keys causes the following:
(use '[clojure.walk :only [stringify-keys]])
(defrecord Rec [x])
(let [record (Rec. "foo")
params {:x "x" :rec record}]
(stringify-keys params))
This causes the following exception: UnsupportedOperationException Can't create empty: user.Rec user.Rec (NO_SOURCE_FILE:1)
Records seem to implement the IRecord marker interface:
user=> (defrecord Rec [x])
user.Rec
user=> (require '[clojure.reflect :as r])
nil
user=> (:bases (r/reflect Rec))
#{java.io.Serializable clojure.lang.IKeywordLookup clojure.lang.IPersistentMap clojure.lang.IRecord java.lang.Object clojure.lang.IObj clojure.lang.ILookup java.util.Map}
user=> (instance? clojure.lang.IRecord (Rec. "hi"))
true
Update
1.6 now has the record? functions
you can check the type of each member and see if it is really a map or something else (where something else is presumed to be a record)
user> (type {:a 1 :b 2})
clojure.lang.PersistentArrayMap