I have a program that plays a little snippet of music. I want it to play in a loop for a while, but I want to be able to stop it gracefully, maybe with a keypress.
(BTW I tried to avoid saying "loop" or "keypress", because I didn't want to steer the answers in that direction.)
I'm still very much a beginner with clojure, and I'm currently just running from the REPL.
Is it time for me to graduate to a better way to run my music function?
How can I tell my function to stop gracefully when I want?
This actually depends on your actual use case: Do you want to kill the music (i.e. interrupt it while playing) or do you just want to prevent it from playing the next time?
The latter case is easily dealt with using a promise that can be filled once you think silence should fall:
(defn play-music! []
(let [p (promise)]
(future
(while (= (deref p 0 ::timeout) ::timeout)
...))
#(deliver p ::stop)))
This returns a function that can be called (without arguments) to stop the loop, e.g.:
(let [stop-fn (play-music!)]
;; ... do important music stuff ...
(stop-fn))
This will stop the loop after the snippet has stopped playing. If you want to really interrupt it, you can use future-cancel (but the actual result of this depends on whether your piece of music is actually interruptible):
(defn play-music! []
(let [fut (future
(while true
...))]
#(future-cancel fut)))
This also returns the stop function. There's a variety of ways to repeatedly perform an operation, most of it are detailed e.g. here, including how to stop the resulting loop.
xsc's answer is sophisticated, informative, and probably better, but it's worth mentioning a very, very simple answer that will probably work: Run it in Leiningen, and stop the function with Ctrl-C, which I consider fairly graceful--though not perfectly graceful.
Related
My application evaluates quoted expressions received from remote clients. Overtime, my system's memory increases and eventually it crashes. What I've found out is that:
When I execute the following code from Clojure's nrepl in a docker container:
(dotimes [x 1000000] ; or some arbitrary large number
(eval '(+ 1 1)))
the container's memory usage keeps rising until it hits the limit, at which point the system will crash.
How do I get around this problem?
There's another thread mentioning this behavior. One of the answers mentions the use of tools.reader, which still uses eval if I need code execution, leading to the same problem.
There's no easy way to get around this as each call to eval creates a new class, even though the form you're evaluating is exactly the same. By itself, JVM will not get rid of new classes.
There are two ways to circumvent this:
Stop using eval altogether (by e.g. creating your own DSL or your own version of eval with limited functionality) or at least use it less frequently, e.g. by batching the forms you need to evaluate
Unload already loaded classes - I haven't done it myself and it probably requires a lot of work, but you can follow answers in this topic: Unloading classes in java?
I don't know how eval exactly works internally,
but based on my observations I don't think your conclusions are correct and also Eugene's remark "By itself, JVM will not get rid of new classes" seems to be false.
I run your sample with -Xmx256m and it went fine.
(time (dotimes [x 1000000] ; or some arbitrary large number
(eval '(+ 1 1))))
;; "Elapsed time: 529079.032449 msecs"
I checked the question you linked and they say it's Metaspace that is growing not heap.
So I observed the Metaspace and it's usage is growing but also shrinking.
You can find my experiment here together with some graphs from JMC console: https://github.com/jumarko/clojure-experiments/commit/824f3a69019840940eaa88c3427515bcba33c4d2
Note: To run this experiment, I've used JDK 17.0.2 on macOS
I have recently watched Rich Hickeys talk at Cojure Conj 2016 and although it was very interesting, I didn't really understand the point in clojure.spec or when you'd use it. It seemed like most of the ideas, such as conform, valid etc, had similar functions in Clojure already.
I have only been learning clojure for around 3 months now so maybe this is due to lack of programming/Clojure experience.
Do clojure.spec and cljs.spec work in similar ways to Clojure and Cljs in that, although they are not 100% the same, they are based on the same underlying principles.
Are you tired of documenting your programs?
Does the prospect of making up yet more tests cause procrastination?
When the boss says "test coverage", do you cower with fear?
Do you forget what your data names mean?
For smooth expression of hard specifications, you need Clojure.Spec!
Clojure.spec gives you a uniform method of documenting, specifying, and automatically testing your programs, and of validating your live data.
It steals virtually every one of its ideas. And it does nothing you can't do for yourself.
But in my - barely informed - opinion, it changes the economy of specification, making it worth while doing properly. A game-changer? - quite possibly.
At the clojure/conj conference last week, probably half of the presentations featured spec in some way, and it's not even out of alpha yet. spec is a major feature of clojure; it is here to stay, and it is powerful.
As an example of its power, take static type checking, hailed as a kind of safety net by so many, and a defining characteristic of so many programming languages. It is incredibly limited in that it's only good at compile time, and it only checks types. spec, on the other hand, validates and conforms any predicate (not just type) for the args, the return, and can also validate relationships between the two. All of this is external to the function's code, separating the logic of the function from being commingled with validation and documentation about the code.
Regarding WORKFLOW:
One archetypal example of the benefits of relationship-checking, versus only type-checking, is a function which computes the substring of a string. Type checking ensures that in (subs s start end) the s is a string and start and end are integers. However, additional checking must be done within the function to ensure that start and end are positive integers, that end is greater than start, and that the resulting substring is no larger than the original string. All of these things can be spec'd out, for example (forgive me if some of this is a bit redundant or maybe even inaccurate):
(s/fdef clojure.core/subs
:args (s/and (s/cat :s string? :start nat-int? :end (s/? nat-int?))
(fn [{:keys [s start end]}]
(if end
(<= 0 start end (count s))
(<= 0 start (count s)))))
:ret string?
:fn (fn [{{:keys [s start end]} :args, substring :ret}]
(and (if end
(= (- end start) (count substring))
(= (- (count s) start) (count substring)))
(<= (count substring) (count s)))))
Call the function with sample data meeting the above args spec:
(s/exercise-fn `subs)
Or run 1000 tests (this may fail a few times, but keep running and it will work--this is due to the built-in generator not being able to satisfy the second part of the :args predicate; a custom generator can be written if needed):
(stest/check `subs)
Or, want to see if your app makes calls to subs that are invalid while it's running in real time? Just run this, and you'll get a spec exception if the function is called and the specs are not met:
(stest/instrument `subs)
We have not integrated this into our work flow yet, and can't in production since it's still alpha, but the first goal is to write specs. I'm putting them in the same namespace but in separate files currently.
I foresee our work flow being to run the tests for spec'd functions using this (found in the clojure spec guide):
(-> (stest/enumerate-namespace 'user) stest/check)
Then, it would be advantageous to turn on instrumenting for all functions, and run the app under load as we normally would test it, and ensure that "real world" data works.
You can also use s/conform to destructure complex data in functions themselves, or use s/valid as pre- and post- conditions for running functions. I'm not too keen on this, as it's overhead in a production system, but it is a possibility.
The sky's the limit, and we've just scratched the surface! Cool things coming in the next months and years with spec!
I am learning clojure, and implementing my standard test project, Tic Tac Toe 10. I have written the same AI in many languages before and have had problems scaling it beyond 6 moves ahead in the other languages also.
I got the AI algorithm basically working, but I'm trying to improve the speed with pmap. Since everything is immutable, I should be able to just drop in pmap in place of map and get the same results, but I'm not seeing that.
(defn get-spot
[board player win-cond levels]
(def avail (get-available board))
(def final
(apply merge
(map #(array-map % (calc-score board player win-cond levels %)) avail)))
final)
But pmap in that spot returns inconsistent results. Not sure where to start looking. I can post more of the code if it's needed.
Replacing def with let everywhere solved the problem. My functions had lots of inconsistent side effects if I didn't use let.
(defn get-spot
[board player win-cond levels]
(let [avail (get-available board)
final (apply merge
(pmap #(array-map % (calc-score board player win-cond levels %)) avail))]
final))
I've written a bunch of clojure code, and read through many tutorials. I don't know how I missed that really important detail.
Please read a book or two about clojure before you even consider to do performance tuning. Having immutability built into a language does not mean you can just replace map by pmap.
Two more things to consider are the absence of side effects for your code and the fact that operations will have to be commutativ.
If they are not, you will have to consider this in your merge algorithm.
As others already said, don't create def bindings insider functions, use let instead. Also, the last expression will be returned from a function anyway, so you don't need to bind final before returning it.
I am sorry for not giving a direct solution to your problem, I just think you need to understand that replacement of map is not as easy as it may seem.
If you still want your problem solved I guess we need to see more code here.
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.