When calling a function that returns something the REPL prints the output. How to suppress this printing without resorting to temporarily adding nil as the last line in a function?
This is fairly easy to do. If, for instance, you have a function named f, then as you know, you can call it like this:
(f)
;; hello yes this is f
;;=> :huge
But if you want to ignore the output, you can do this instead:
(do (f) nil)
;; hello yes this is f
;;=> nil
You could also define an ignore function to do this for you if you feel like it:
(def ignore (constantly nil))
(ignore (f))
;; hello yes this is f
;;=> nil
Related
Given the following function
(defn func []
(break!))
I want the break! function to start a repl, and inside that repl I can print the callstacks that invokes func.
The feature is like ipdb in Python, which comes quite handy when we want to interactively investigate inside the runtime of some function.
A very basic version could just be:
(defn break! [] (clojure.main/repl))
That will start a new, nested REPL, and when you exit it (with ^D -- or ^Z on Windows), it will continue on.
You can't evaluate locals, but if you write break! as a macro, you can at least display the active locals before starting the REPL:
user=> (defmacro break! []
(let [locals (into {} (map (juxt keyword identity)) (keys &env))]
(prn locals)
(clojure.main/repl :prompt #(print "nested> "))))
#'user/break!
user=> (defn foo "Using the break! function." [a b] (break!))
#'user/foo
user=> (foo 13 42)
{:a 13, :b 42}
nested> (doc foo)
-------------------------
user/foo
([a b])
Using the break! function.
nil
nested> ^D
nil
user=>
If you want the stacktrace as data inside the nested REPL, you can evaluate (:trace (Throwable->map (Throwable.)))
I was practicing one Clojure tutorial and had to ensure that a for loop was executed so I put a println command there, but it did not display messages.
So now I have got the question...
This code prints Tom's name:
(ns tutorial.core)
(defn -main []
(println 'Jane)
(for [a ['Tom]]
(println a))
;; 'Kate
)
tutorial.core> (-main)
Jane
Tom
(nil)
tutorial.core>
but this not:
(ns tutorial.core)
(defn -main []
(println 'Jane)
(for [a ['Tom]]
(println a))
'Kate
)
tutorial.core> (-main)
Jane
Kate
tutorial.core>
Why? In which cases can we expect that println will not print texts?
for is not a loop, it is a sequence comprehension which returns a lazy sequence. Your for expression will therefore only execute its side-effects (calls to println) when the returned sequence is evaluated. The REPL evaluates the values returned from your calls to -main so it can print them.
Your first example returns a lazy sequence which is evaluted by the REPL causing the (println 'Tom) call to be evaluated. Since println returns nil, the resulting sequence contains a single nil value - this is the (nil) you see in the output.
Your second example creates the same sequence but does not evaluate it, instead 'Kate is returned from the function and the REPL prints that.
If you want an imperative for loop you should use doseq:
(defn -main []
(println 'Jane)
(doseq [a ['Tom]]
(println a))
'Kate)
As Lee says, if you only want side effects like printing, a doseq is the best solution as it never returns a value other than nil.
If you do want to use a for loop, you can remove the laziness by wrapping it inside a (vec ...) expression, which will force the for loop to run immediately. Thus we get:
(println :start)
(vec
(for [a [1 2 3]]
(println a)))
(println :end)
with result:
:start
1
2
3
:end
Without the vec, we get the behavior you saw:
(println :start)
(for [a [1 2 3]]
(println a))
(println :end)
with result:
:start
:end
I almost never want a lazy result, as the uncertainty over when a computation occurs can make debugging difficult. I use the above construct so often that I wrote a small macro forv that always returns a vector result, similar to the mapv function.
Update: Thank you everyone for your responses, but I seem to have made a bad choice using an embedded "def" in my example, which is throwing people off. This has nothing to do with def. The problem still occurs if I do not use a def. As to why I'm doing it this way -- honestly, I'm just trying to learn about macros, and this is just one of the ways that occurred to me. I'm just trying to understand how macros work. I may very well ultimately end up using a different mechanism. I also know that having multiple defs (including defmacros) for the same thing is considered bad practice, but it still seems to me this way should work.
I am re-factoring my examples:
When I write variations of a macro-generating macro in-line (with a simplified version of what I'm actually doing):
(do
(defmacro abc []
`(defmacro xyz []
;;(def x 7)))
(+ 7 1)))
(abc)
;;(xyz)
;;(spit "log.txt" (format "pass 1: x=%s\n" x ) :append false))
(spit "log.txt" (format "pass 1: results=%s\n" (xyz) ) :append false))
(do
(defmacro abc []
`(defmacro xyz []
;;(def x 8)))
(+ 8 1)))
(abc)
;;(xyz)
;;(spit "log.txt" (format "pass 2: x=%s\n" x ) :append true))
(spit "log.txt" (format "pass 1: results=%s\n" (xyz) ) :append false))
(do
(defmacro abc []
`(defmacro xyz []
;;(def x 9)))
(+ 9 1)))
(abc)
;;(xyz)
;;(spit "log.txt" (format "pass 3: x=%s\n" x ) :append true))
(spit "log.txt" (format "pass 1: results=%s\n" (xyz) ) :append false))
It gives me what I expect:
pre-refactor:
cat log.txt
pass 1: x=7
pass 2: x=8
pass 3: x=9
post-refactor:
cat log.txt
pass 1: results=8
pass 2: result=9
pass 3: result=10
But when I try to iterate using doseq, it only seems to give me one value:
(def int-lookup [7 8 9])
(doseq [i (range 3)]
(defmacro abc []
`(defmacro xyz []
;;(def x ~(int-lookup i))))
(+ 1 ~(int-lookup i))))
(abc)
;;(xyz)
;;(spit "log.txt" (format "pass %s: x=%s\n" i x) :append (if (= i 0) false true)))
(spit "log.txt" (format "pass %s: result=%s\n" i (xyz)) :append (if (= i 0) false true))
Output:
pre-refactor:
cat log.txt
pass 0: x=9
pass 1: x=9
pass 2: x=9
post-refactor
cat log.txt
pass 0: result=10
pass 1: result=10
pass 2: result=10
I've seen it give me all 7's, and all 8's too, but never mixed.
I've tried resetting the macro symbols in-between like so:
(ns-unmap *ns* 'xyz)
(ns-unmap *ns* 'x)
However, this make things even worse, sporadically generating:
CompilerException java.lang.RuntimeException: Unable to resolve symbol: xyz in this context, compiling:(/tmp/form-init2424586203535482807.clj:5:5)
I'm sort of assuming the compiler is somehow optimizing the macro def or call, so it's only actually driving it once when using doseq. If this is the case, then how would you iterate over defmacro definitions and not have this happen? I intend to have about 15 iteration is my final solution, so I really don't want to have to in-line all definitions.
I'm pretty sure I know what's happening. It's a classic macro thing -- distinguishing between compile-time and run-time.
I think that when the do-seq is being compiled, the compiler needs to get something to put into the '(xyz) expression:
(spit "log.txt" (format "pass %s: result=%s\n" i (xyz)) <-- Compiler: what do I put here?....
I'm assuming it will come from the run-time value of 'xyz that is set by the prior defmacro:
(defmacro abc []
`(defmacro xyz [] <-- I'm assuming this version will be used
(+ 9 1)))
(abc)
while 'abc is known at the compile-time of the do-seq, the underlying macro 'xyz in the 'abc defmacro is only known at run-time. The compiler only knows about the 'xyz symbol set from my previous run, which returns 10. Thus the compiler statically inserts this expression, and ignores the runtime version, which why I see the same value each time.
I have a function like this:
(defn foo [{a :keya b :keyb}]
(list a b))
And i'm calling it like this:
(foo {:keya "hi"}) ; Returns ("hi" nil)
If I don't give keyb keyword argument, it takes nil for that. Is there a way to ensure that it throws exception for it instead of taking it as nil.
( I know that I can manually check and throw an exception, but is there any special option which enforces the constraints.)
You can use a precondition (http://clojure.org/special_forms#toc9) to assert the key is present:
(defn foo [{a :keya b :keyb}]
{:pre [(not (nil? b))]}
(list a b))
This will throw an AssertionError when the key is nil.
No, but of course because Clojure is a lisp you can define your own macro that handles the boring "manual checking" for you automatically.
aldazosa gave you the right solution, but {:keya nil :keyb nil} is the valid map too. To allow nil values you may use contains? instead of nil? check:
(defn foo [{a :keya b :keyb :as m}]
{:pre [(every? (partial contains? m)
[:keya :keyb])]}
(list a b))
If you want something more complex look at Validateur or bouncer
Given a list of names for variables, I want to set those variables to an expression.
I tried this:
(doall (for [x ["a" "b" "c"]] (def (symbol x) 666)))
...but this yields the error
java.lang.Exception: First argument to def must be a Symbol
Can anyone show me the right way to accomplish this, please?
Clojure's "intern" function is for this purpose:
(doseq [x ["a" "b" "c"]]
(intern *ns* (symbol x) 666))
(doall (for [x ["a" "b" "c"]] (eval `(def ~(symbol x) 666))))
In response to your comment:
There are no macros involved here. eval is a function that takes a list and returns the result of executing that list as code. ` and ~ are shortcuts to create a partially-quoted list.
` means the contents of the following lists shall be quoted unless preceded by a ~
~ the following list is a function call that shall be executed, not quoted.
So ``(def ~(symbol x) 666)is the list containing the symboldef, followed by the result of executingsymbol xfollowed by the number of the beast. I could as well have written(eval (list 'def (symbol x) 666))` to achieve the same effect.
Updated to take Stuart Sierra's comment (mentioning clojure.core/intern) into account.
Using eval here is fine, but it may be interesting to know that it is not necessary, regardless of whether the Vars are known to exist already. In fact, if they are known to exist, then I think the alter-var-root solution below is cleaner; if they might not exist, then I wouldn't insist on my alternative proposition being much cleaner, but it seems to make for the shortest code (if we disregard the overhead of three lines for a function definition), so I'll just post it for your consideration.
If the Var is known to exist:
(alter-var-root (resolve (symbol "foo")) (constantly new-value))
So you could do
(dorun
(map #(-> %1 symbol resolve (alter-var-root %2))
["x" "y" "z"]
[value-for-x value-for-y value-for z]))
(If the same value was to be used for all Vars, you could use (repeat value) for the final argument to map or just put it in the anonymous function.)
If the Vars might need to be created, then you can actually write a function to do this (once again, I wouldn't necessarily claim this to be cleaner than eval, but anyway -- just for the interest of it):
(defn create-var
;; I used clojure.lang.Var/intern in the original answer,
;; but as Stuart Sierra has pointed out in a comment,
;; a Clojure built-in is available to accomplish the same
;; thing
([sym] (intern *ns* sym))
([sym val] (intern *ns* sym val)))
Note that if a Var turns out to have already been interned with the given name in the given namespace, then this changes nothing in the single argument case or just resets the Var to the given new value in the two argument case. With this, you can solve the original problem like so:
(dorun (map #(create-var (symbol %) 666) ["x" "y" "z"]))
Some additional examples:
user> (create-var 'bar (fn [_] :bar))
#'user/bar
user> (bar :foo)
:bar
user> (create-var 'baz)
#'user/baz
user> baz
; Evaluation aborted. ; java.lang.IllegalStateException:
; Var user/baz is unbound.
; It does exist, though!
;; if you really wanted to do things like this, you'd
;; actually use the clojure.contrib.with-ns/with-ns macro
user> (binding [*ns* (the-ns 'quux)]
(create-var 'foobar 5))
#'quux/foobar
user> quux/foobar
5
Evaluation rules for normal function calls are to evaluate all the items of the list, and call the first item in the list as a function with the rest of the items in the list as parameters.
But you can't make any assumptions about the evaluation rules for special forms or macros. A special form or the code produced by a macro call could evaluate all the arguments, or never evaluate them, or evaluate them multiple times, or evaluate some arguments and not others. def is a special form, and it doesn't evaluate its first argument. If it did, it couldn't work. Evaluating the foo in (def foo 123) would result in a "no such var 'foo'" error most of the time (if foo was already defined, you probably wouldn't be defining it yourself).
I'm not sure what you're using this for, but it doesn't seem very idiomatic. Using def anywhere but at the toplevel of your program usually means you're doing something wrong.
(Note: doall + for = doseq.)