Let's say we need evaluate a number of clauses in a source file, e.g.
test.clj
#(def x 1)
#(def y 2)
#(def z 3)
Only the last evaluation shows up if we plainly use either clj or lein repl,
user => (load-file "test.clj")
3
We can surround each of them by println to show all of them,
test-with-println.clj
(println #(def x 1))
(println #(def y 2))
(println #(def z 3))
user => (load-file "test-with-println.clj")
1
2
3
nil
What are the better alternatives to avoid invasive printlns all over the source code while able to print out all the intended evaluations under the umbrella of REPLs?
#Solution
Thanks to tap> from the answer #Sean Corfield we can have desired results as follows,
pipe every wannabe printed out to tap>.
test-with-tap.clj
(-> #(def x 1) tap>)
(-> #(def y 2) tap>)
(-> #(def z 3) tap>)
REPLs will receive none of their outputs until tap> is turned on by add-tap.
user=> (load-file "test-with-tap.clj")
nil
user=> (add-tap #(def out (bound-fn* println)))
nil
user=> (load-file "test-with-tap.clj")
1
2
3
user=> (remove-tap out)
nil
user=> (load-file "test-with-tap.clj")
nil
tap> is probably what you're looking for - https://clojuredocs.org/clojure.core/tap%3E - This lets you send full Clojure values (not just strings) to any function registered as a listener, which can be something like Portal for example - https://github.com/djblue/portal - which is something I use all-day, every-day, but you can also use something as simple as println in add-tap to get every tap>'d value displayed.
The tap> calls can stay in your code, even in production, since there is next to no overhead to using them.
Although tap> returns a Boolean, you can use (doto expr tap>) to evaluate and return expr but still send the value to any tap listeners. tap> is a great debugging tool.
I haven't had a chance to play with tap> yet. My favorite over the years has been the spy family of functions in the Tupelo library. Specifically, check out spyx, spyx-pretty, and let-spy.
Related
This question already has answers here:
Why isn't my code printing like it should?
(3 answers)
Closed 2 years ago.
(defn f1 []
(for [a [1 2]]
a))
;user=>(f1)
;(1 2)
(defn f2 []
(for [a [1 2]]
(prn a)))
;user=>(f2)
;1
;2
;(nil nil)
(defn f3 []
(for [a [1 2]]
(prn a))
'something-else)
;user=>(f3)
;something-else
Why does f3 not print 1 and 2 before printing 'something-else?
i.e. I expected and had assumed (wrongly) it would print the following:
; 1
; 2
; something-else
Came across this when using a for with a lot of code inside it and this played havoc with
my attempt to use prn statements to trace the value of variables while debugging.
i.e. prn and println do not print out. I think it's only when the for block is not the
final form in its enclosing form, but i'm still not sure what's going on.
The point being that a side-effect such as prn or println, should not require to be in return value position for it to fire. So there's something deeper with list comprehensions that I don't understand.
A notion as I write this - maybe in f3 the list comprehension is simply never evaluated, due to laziness? ... oh [censored].
Yes, that is indeed it:
(defn f4 []
(doall
(for [a [1 2]]
(prn a)))
'something-else)
user=> (f4)
;1
;2
;something-else
So, even though mostly solved, I will still post this question to consolidate the learning - would anyone care to post some examples of their own gotchas re. laziness.
As you have documented here, the macro for is lazy, and doesn't execute until it has to. You can force it by wrapping it in a (vec ...) form or a doall.
For debugging purposes especially, I like to use spyx and forv from the Tupelo library to avoid all of these gotchas:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn f5 []
(forv [a [1 2]]
(spyx a))
(spy :returning :something-else))
(dotest
(spyx (f5)))
With result:
-------------------------------
Clojure 1.10.1 Java 14
-------------------------------
Testing tst.demo.core
a => 1
a => 2
:returning => :something-else
(f5) => :something-else
Ran 2 tests containing 1 assertions.
0 failures, 0 errors.
So you can see printed nicely:
the labeled value of a at each step of the forv loop.
the return value of the function with a custom label
the explicit value of the function call (f5)
nothing anywhere is lazy
spy, spyx, et al always return the value printed for further use
a convenient unit test via is= confirms the output value.
There is a nice template project that you can clone to get you started quickly.
You may also be interested in with-result, or just doseq. Don't forget the Clojure CheatSheet.
I am looking for a way to determine if a function printed (using println or anything similar).
What I am trying to determine is if test-vars printed something or not.
The issue with this function is that it doesn't return anything, but only print things when errors got issues, but I want to know if it succeeded or not and the only way I see to know it is to check if it printed something or not.
Even better would be a way to "intercept" what is going to out and to put it in a variable.
After the comments from #lee and #leetwinski I tried the following:
(deftest test-1
(testing
(is (= 1 2))))
Then I tried to run that test using:
(let [printed (with-out-str (test-vars [#'test-1]))]
(print (str "Printed size: " (count printed))))
But here is what I got:
FAIL in (test-1) (form-init505699766276988020.clj:103)
expected: (= 1 2)
actual: (not (= 1 2))
Printed size: 0
nil
So, what test-vars outputs has been outputted anyway. Then printed was empty.
in addition to #Lee's answer: in general you could just rebind *out* to any other writer you want:
temporary binding:
user> (binding [*out* (java.io.StringWriter.)]
(println 101)
(str *out*))
"101\n"
is just an analogue to with-out-str
thread-local binding:
user> (set! *out* (java.io.StringWriter.))
#object[java.io.StringWriter 0x575e6773 ""]
user> (println 123)
nil
user> (str *out*)
"123\n"
here we rebind the *out*, for the current thread (and for all the threads, spawned from it, AFAIK).
You can use with-out-str which intercepts printed values and collects them into a string:
(let [printed (with-out-str (test-vars))]
...)
Consider the following macro:
(defmacro somemacro []
(list 'let ['somevar "Value"] 'somevar))
Expanding it yields the following result:
(macroexpand '(somemacro))
Result:
(let* [somevar "Value"] somevar)
I have two questions about let* (with the asterisk):
What does it mean? (In particular: is it documented somewhere?)
Why is the macro not expanded with the 'normal' let? (I.e., let without the asterisk.) Both yield the same result (in my experimentation). Is there a counter example?
Unluckily I could not find any 'official' documentation about let*, that's why I'm asking here.
Sources I've already considered:
(doc let*) ; --> nil
(source let*) ; --> source not found
https://clojuredocs.org/clojure.core --> I see not let* here
(although there is e.g. list*)
https://clojuredocs.org/clojure.core/let --> only mentioned once in
a comment, that is not totally clear to me:
Nota Bene: let in Clojure is like let* in Scheme -- each init-expr has access to the preceding binding forms. (There is also a let*, but it is more or less let without destructuring, and in fact is the underlying implementation.)
LET versus LET* in Common Lisp
--> this question is about common lisp, but maybe it's the same in Clojure?
This answer: https://stackoverflow.com/a/5084339/3398271
In Clojure it basically means "foo* is like foo, but somehow different, and you probably want foo". In other words, it means that the author of that code couldn't come up with a better name for the second function, so they just slapped a star on it.
--> Is this the case for let and let*? But if so, still the question remains, what is exactly the difference?
What is the difference between let and let* in Scheme? --> Is this the same in Clojure?
let* is an internal implementation detail. let is a macro implemented in terms of let*. https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L4301
The macro let adds parameter destructuring to let*. This is the standard pattern for xyz and xyz* in Clojure, with the * version not being documented. An exception being list and list*.
I thought I would add that the reason why macroexpand returns let* instead of let can be found in the documentation of macroexpand:
Repeatedly calls macroexpand-1 on form until it no longer
represents a macro form, then returns it.
So what happens is the first call of macroexpand-1 returns (let [somevar "Value"] somevar), and the second expands let into let*.
Indeed,
user=> (println (clojure.string/join "\n" (take 3 (iterate macroexpand-1 '(somemacro)))))
(somemacro)
(let [somevar "Value"] somevar)
(let* [somevar "Value"] somevar)
nil
If you were to use destructuring in your macro, the output would be more interesting:
user=> (defmacro destructuring-macro [] `(let [[x y z] [:x :y :z]] y))
#'user/destructuring-macro
user=> (println (clojure.string/join "\n" (take 3 (iterate macroexpand-1 '(destructuring-macro)))))
(destructuring-macro)
(clojure.core/let [[testing.core/x testing.core/y testing.core/z] [:x :y :z]] testing.core/y)
(let* [vec__8356 [:x :y :z] x (clojure.core/nth vec__8356 0 nil) y (clojure.core/nth vec__8356 1 nil) z (clojure.core/nth vec__8356 2 nil)] testing.core/y)
nil
Notice that let is fully qualified by the syntax quote, because it is not a special form (even though its documentation says it is). The underlying special form is let*, which is not fully qualified by the syntax quote.
I asked a similar question yesterday but it seemed I had to change my approach, so I did, but now I'm sort of stuck again.
Anyway, what I want to do is something along the line of
(def bar '(* 2 %))
(#(bar) 2) ;this line doesn't work.
(#(* 2 %) 2) ;this is what I want the line that doesn't work to do.
Thing is, I want the expression stored in a var so I could do something like
(def bar2 (list (first bar) 3 (nth bar 2)))
(#(bar2) 2) ;this line obviously doesn't work either.
Maybe there's another approach than the # anonymous function reader macro.
I'm doing a project in genetic programming for uni so what I need to do is have an expression that I can change and make into a function.
(def bar '(* 2 %))
((eval (read-string (str "#" bar))) 3)
=> 6
If you used named parameter(s) in expression it would look cleaner:
(def bar '(* 2 p))
(def f-expr (concat '(fn [p]) [bar]))
((eval f-expr) 3)
=> 6
If you want to evaluate quoted expressions at run time (as opposed to compile time, à la macros), you can just use eval:
(eval '(* 10 12))
;=> 120
(def arg 12)
(def bar '(* 10 arg))
(eval bar)
;=> 120
Normally one steers clear of eval (macros will perform better, for one thing), but it might be what you want for playing with genetic algorithms.
I am trying to build a quick toc from an html content. (to make it short)
The code is dead simple:
(defn toc [content]
(doseq [i (take 5 (iterate inc 1))]
(let [h (str "h" i)]
(println ($ content h)))))
where content is the html content, and $ is a macro required from clojure-soup
While
($ content "h1")
works, and returns a list of all the tags.
Simple:
($ content (str "h" 1))
just won't make it whatever I do.
How do I force
(str "h" 1)
to be properly eval-ed before the macro is called ?
Bonus points for explaining why :)
This is not possible if, as you imply, $ is a macro: it's simply not how macros work. The macro needs to expand into something, at compile time, and it can only do so once. You have run-time data, like the various values of h, but there is no way to use that at compile-time. To me it sounds like $ should have been a function.
Amalloy answer the questions why part. For making it work part you will need to use eval .
In place of ($ content h) use
(eval `($ content ~h))
Another explanation for why this is so is based on the fact that what operations does the macro do at compile time and what it does at runtime (i.e what code it emits). Below is such an example to clear things out.
(def user "ankur")
(defmacro do-at-compile [v] (if (string? v) `true `false))
(defmacro do-at-runtime [v] `(if (string? ~v) true false))
(do-at-compile "hello") ;; => true
(do-at-compile user) ;; => false, because macro does perform the check at compile time
(do-at-runtime "hello") ;; => true
(do-at-runtime user) ;; => true
The $ macro is doing the calculations on the passed second parameter at compile time and hence it is not working in your particular case.