I am having a hard time understanding the point of this example:
(let [result (future (println "this prints once")
(+ 1 1))]
(println "deref: " (deref result))
(println "#: " #result))
The author explains:
Notice that the string "this prints once" indeed prints only once, even though you dereference the future twice. This shows that the future’s body ran only once and the result, 2, got cached.
I don't get it; the string will print once even without dereferencing the future. What is this example supposed to teach?
I agree this is subtle. The point of this is to show that future is a one-time evaluation. Sure, the println side effect occurs whether you deref "result" or not. In fact, the side effect occurs without later deref-ing "result" as you've noted. Merely binding "result" causes the println side effect to occur.
More importantly, the idea here is that deref-ing "result" twice explicitly does not cause it to be evaluated (or bound) twice. In other words, it does not cause the println side effect twice. You get the cached value of 2 both times you deref it.
One might expect deref-ing it twice would cause it to be bound twice, and therefore execute the println twice. But this is not the case. Instead, you get the cached, deref-ed value just once. The point here is more that the side effect occurs upon binding, not upon deref-ing, and that deref-ing twice does not incur a second binding.
The future executes the enclosed code in a separate thread and starts the execution immediately so it will run the code even if you don't reference the result value.
I guess the author wanted to show that the future body won't be reexecuted when you dereference it more than once.
Related
I defined a function play like so:
(let [play-switch (fn [c]
(condp = c
:scales (play-scale)
:intervals (play-interval)
:chords (play-chord)
:inversions (play-inversion)
(print "play error, invalid :practice_mode state")))]
(def ^:dynamic play
"if no argument, evaluates the appropriate play-<mode> function, based on the current state of #opts.
if one argument, does the corresponding play-<mode> function."
(fn
([] (play-switch (get #opts :practice_mode)))
([method] (play-switch method)))))
When I call play in my application like (play), its intended side effect does not occur. However, when I play in my application like (clojure.tools.trace/dotrace [play] (play)). How could tracing a function affect what it does?
Tracing a function can force the realization of otherwise unrealized lazy sequences.
Such problems are very commonly instances of "the dreaded lazy bug" where the side effects (aka the work) of one of the functions is being run in a lazy sequence. This has the frusterating effect that if you call the function directly from the REPL the side effect happens as the result is printed and if you call it with trace the lazy sequence is realized when trace prints the result. Though in the normal case the side effects never happen because the lazy sequence it not realized.
put calls to doall (if you need the result) or dorun (if you don't need the result) around each side effecting lazy sequence.
Why does this bit of Clojure code:
user=> (map (constantly (println "Loop it.")) (range 0 3))
Yield this output:
Loop it.
(nil nil nil)
I'd expect it to print "Loop it" three times as a side effect of evaluating the function three times.
constantly doesn't evaluate its argument multiple times. It's a function, not a macro, so the argument is evaluated exactly once before constantly runs. All constantly does is it takes its (evaluated) argument and returns a function that returns the given value every time it's called (without re-evaluating anything since, as I said, the argument is evaluated already before constantly even runs).
If all you want to do is to call (println "Loop it") for every element in the range, you should pass that in as the function to map instead of constantly. Note that you'll actually have to pass it in as a function, not an evaluated expression.
As sepp2k rightly points out constantly is a function, so its argument will only be evaluated once.
The idiomatic way to achieve what you are doing here would be to use doseq:
(doseq [i (range 0 3)]
(println "Loop it."))
Or alternatively dotimes (which is a little more concise and efficient in this particular case as you aren't actually using the sequence produced by range):
(dotimes [i 3]
(println "Loop it."))
Both of these solutions are non-lazy, which is probably what you want if you are just running some code for the side effects.
You can get a behavior close to your intent by usig repeatedly and a lambda expression.
For instance:
(repeatedly 3 #(println "Loop it"))
Unless you're at the REPL, this needs to be surrounded by a dorun or similar. repeatedly is lazy.
I have a bit of computation that is somewhat expensive (starting a database), and I only want to create the database if I actually am going to use it. I am looking for a reference variable (or just a plain variable, if that is possible) that would only evaluate its value in the event that it is used (or dereferenced). Something conceptually like the following.
(def v (lazy-var (fn [] (do (println "REALLY EXPENSIVE FUNCTION") true))))
and in the future, when I either just use var v, or call #v, I then get it to print out "REALLY EXPENSIVE FUNCTION", and from thereon v has a value of true. The important thing here is that the fn was not evaluated until the variable was (de)referenced. When needed, the function is evaluated once and only once to calculate the value of the variable. Is this possible in clojure?
delay would be perfect for this application:
delay- (delay & body)
Takes a body of expressions and yields a Delay object that will invoke the body only the first time it is forced (with force or deref/#), and will cache the result and return it on all subsequent force calls.
Place the code to construct the database handle within the body of a delay invocation, stored as a Var. Then dereference this Var whenever you need to use the DB handle — on the first dereference the body will be run, and on subsequent dereferences the cached handle will be returned.
(def db (delay (println "DB stuff") x))
(select #db ...) ; "DB stuff" printed, x returned
(insert #db ...) ; x returned (cached)
Clojure 1.3 introduced memoize function for this purpose:
(memoize f)
Returns a memoized version of a referentially transparent function.
The memoized version of the function keeps a cache of the mapping from
arguments to results and, when calls with the same arguments are
repeated often, has higher performance at the expense of higher memory
use.
In your example replace non-existing lazy-var with memoize:
(def v (memoize (fn [] (do (println "REALLY EXPENSIVE FUNCTION") true))))
(v)
=>REALLY EXPENSIVE FUNCTION
=>true
(v)
=>true
(delay expr) also does the job as another answer explains. An extra comment on dereferencing the delay - the difference between force and deref/# is that force does not throw exception if used on non-delay variable while deref/# may throw ClassCastException "cannot be cast to clojure.lang.IDeref".
I'm calling clojure.core/time which is documented as "Evaluates expr and prints the time it took. Returns the value of expr"
Eg:
(time (expensive))
Macroexpanding it shows that it does store the value as a let so after outputting the time it should return immediately with the value in the let expression.
When I make the call however with an expensive computation, I see a delay and then get the time back, but then have to wait for a significant time (sometimes +10 seconds or more) for the result to appear.
Can anyone explain what's going on here?
PS: This is using clojure 1.3.0 if that makes any difference.
Maybe you are returning something lazy, of which the elements are only produced when fed to the REPL? In that case, you might want to wrap it in a dorun which forces all elements to be produced.
If you could provide the details of your expensive computation, we could see if this is true.
Useful addition from Savanni D'Gerinel's comment:
The proper syntax is probably (time (doall (computation))) if you want to return the result and (time (dorun (computation))) if you do not.
I'm having some trouble understanding how the delay macro works in Clojure. It doesn't seem to do what expect it to do (that is: delaying evaluation). As you can see in this code sample:
; returns the current time
(defn get-timestamp [] (System/currentTimeMillis))
; var should contain the current timestamp after calling "force"
(def current-time (delay (get-timestamp)))
However, calling current-time in the REPL appears to immediately evaluate the expression, even without having used the force macro:
user=> current-time
#<Delay#19b5217: 1276376485859>
user=> (force current-time)
1276376485859
Why was the evaluation of get-timestamp not delayed until the first force call?
The printed representation of various objects which appears at the REPL is the product of a multimethod called print-method. It resides in the file core_print.clj in Clojure's sources, which constitutes part of what goes in the clojure.core namespace.
The problem here is that for objects implementing clojure.lang.IDeref -- the Java interface for things deref / # can operate on -- print-method includes the value behind the object in the printed representation. To this end, it needs to deref the object, and although special provisions are made for printing failed Agents and pending Futures, Delays are always forced.
Actually I'm inclined to consider this a bug, or at best a situation in need of an improvement. As a workaround for now, take extra care not to print unforced delays.