This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-20
Channels
- # announcements (1)
- # architecture (14)
- # asami (21)
- # babashka (1)
- # beginners (44)
- # biff (6)
- # calva (24)
- # clojure (16)
- # clojure-europe (12)
- # clojurescript (32)
- # cursive (23)
- # datascript (5)
- # honeysql (8)
- # hyperfiddle (1)
- # malli (1)
- # nextjournal (34)
- # nrepl (4)
- # off-topic (64)
- # re-frame (12)
- # reagent (1)
- # releases (2)
- # reveal (41)
- # shadow-cljs (137)
- # spacemacs (4)
- # xtdb (5)
(def task-run-state (atom true))
(defn task-stop
[]
(reset! task-run-state false)
)
(defn task-start
[]
(reset! task-run-state true))
(defn run
[]
(println "run!")
(loop [x 10]
(println "task-run-state:" @task-run-state)
(when (and (> x 0) @task-run-state)
(println "run:" x)
(Thread/sleep 1000)
(recur (- x 1))))
)
(comment
(let [r (future (run))]
@r)
(task-start)
(task-stop)
)
When I press alt+enter calc (let [r (future (run))] @r)
and loop print . why I press alt+enter calc (task-stop
to change atom task-run-state , the program is run continue, why is not stop?Because you have @r
so that will wait for the future
to complete.
So evaluating the let
is just going to run until it completes. Other evaluations won't happen until it has finished.
If you evaluate just (future (run))
it will "complete", i.e., return a value, immediately because you'll get the future object itself back while the code runs in another thread. Then you can eval (task-stop)
and you'll see it affect the loop.
Like so (using a REPL directly):
user=> (future (run))
run!
task-run-state: true
run: 10
#object[clojure.core$future_call$reify__8477 0x2b9b7f1f {:status :pending, :val nil}]
user=> task-run-state: true
run: 9
task-run-state: true
run: 8
task-run-state: true
run: 7
task-run-state: true
run: 6
(task-stop)
false
user=> task-run-state: false
It stops here.With @r
, you see the first expression run to completion before the (task-stop)
can run:
user=> (let [r (future (run))] @r)
run!
task-run-state: true
run: 10
task-run-state: true
run: 9
task-run-state: true
run: 8
task-run-state: true
run: 7
task-run-state: true
run: 6
task-run-state: true
run: 5
(task-stop)
task-run-state: true
run: 4
task-run-state: true
run: 3
task-run-state: true
run: 2
task-run-state: true
run: 1
task-run-state: true
nil
user=> false
ok. thanks. I want to run a task in the background and be able to manually stop it. am i wrote this code correctly
Hi, what book of the many for Clojure would you recommend after picking up some syntax - so that it deals mostly with database access (or similar) and api building?
next.jdbc for relational database access has some excellent docs https://cljdoc.org/d/com.github.seancorfield/next.jdbc/1.2.761/api/next.jdbc
I've also done some guides on using next.jdbc to build a server side application https://practical.li/clojure-web-services/projects/banking-on-clojure/development-database.html
appreciate it
Clojure Applied is a good book about practical use of Clojure (although the author says they would play down records if they do a 2nd ed and focus more on plain hash maps).
Hello everyone, a question regarding ->>
, I have searched through the https://clojuredocs.org/clojure.core/-%3E%3E and I understood what it's doing but I'm very unsure when to use it.
The docs have a nice example (the one using reduce) which makes a lot of sense in terms of readability but I'm quite sure it's not something I would have came up with (perhaps it's something that comes with experience but I'd still rather ask), so - any thumb rule when we want to use this?
You can check the threading macro guide: https://clojure.org/guides/threading_macros
When to use it is down to preference. The more nested expressions in the top-level expression, the more likely the thread macros would be used. If a threaded macro is macro-expanded, then an equo Clojure nested expression is returned.
The thread macro can make it clearer as to the flow of transformations being applied to the data. For a nested expression, then it is read from the most nested expression outwards to understand the flow.
Ty for the quick replies!
@U7S5E44DB - I find -> quite intuitive to use (as it's like the .
sign for objects in Python (although we have no objects here, that's some similarity which eases the understanding that I hope is correct 🙂 )
It's about the ->> which I don't understand quite well
@U05254DQM gave some nice insights that help, I'll combine it was the macro guide sent which is sure to be helpful.
Yet again, ty both!
One final point. The thread macros can make debugging a flow easier. I use the #_ to comment one of more of the expressions in the thread. Then evaluate the top level form to see the results of the partial flow
Use ->> to flow a sequence through a series of transformations
There is an example of this in the video https://youtu.be/hpz2vHaTz44
I’m following the style suggested by Stuart Sierra https://stuartsierra.com/2018/07/06/threading-with-style
Hello. I have learned and forgotten the syntax and notation for Clojure a few times, and written some fun toy applications with the core language, but I don't know anything about Lein, or installing and managing dependencies, or whatever other tools there are. I've learned to write and evaluate with emacs and cider pretty effectively as I do with SBCL, but I don't know anything beyond that. Q: If anyone can share resources for how to learn the environment for someone who already is familiar with the core language, it would be greatly appreciated.
Maybe start with the https://clojure.org/guides/deps_and_cli, and check out https://github.com/seancorfield/deps-new if you don't want to set everything up by hand.
A practical guide to the Clojure CLI tooling for working with Clojure projects https://practical.li/clojure/clojure-cli/
Hi everyone - I'm reading 'The Joy of Clojure (2ed)'. Two functions are defined on p126 illustrating the difference between rest
and next
with regard to lazy sequences. I don't understand the difference, especially since when I run the code I do not get the claimed results. Could someone clarify what is going on here please? - Am I allowed to paste the yellow block from the book?
I think it should be fine pasting short snippets of code here. I also wouldn't be surprised if there were a public repo somewhere with those code snippets in it.
It is at least possible that this level of detailed behavior might have been intentionally changed in some older version of Clojure.
Thanks Andy - I'll paste it
Thanks for looking at it. Do you use rest
or next
in your code? next
seems more useful when used with when-let
but rest
seems to be more highly recommended.
I am primarily a hobbyist in Clojure, and in the code I have written, I've never noticed the difference between rest
vs. next
.
I'm also a hobbyist! It's great fun, isn't it?
Definitely!
I do not know why, but I see slightly different output depending on whether I run that code with Clojure 1.6.0 vs. later versions of Clojure.
I believe the general recommendation is that if you want to guarantee control over how many things are evaluated in a sequence, then do not use lazy sequences. Use things like loop instead.
Because lazy sequences can in many cases evaluate more elements than the minimum possible.
Joy of Clojure 2nd ed has a publish year of 2014. Clojure 1.6.0 was release 2014-Mar-25, Clojure 1.7.0 on 2015-Jun-30.
Thanks Andy - I'll carry on reading and see whether that calms my nerves
@neil.barrett16 Something changed between Clojure 1.6 and 1.7 that caused this difference to go away -- I suspect iterate
changed:
(! 748)-> clj -M:1.6
Clojure 1.6.0
user=> (def very-lazy (-> (iterate #(do (print \.) (inc %)) 1)
rest rest rest))
..#'user/very-lazy
user=> (def less-lazy (-> (iterate #(do (print \.) (inc %)) 1)
next next next))
...#'user/less-lazy
user=> (println (first very-lazy))
.4
nil
user=> (println (first less-lazy))
4
nil
user=> ^D
Sun Feb 20 13:35:00
(sean)-(jobs:0)-(~/clojure/fresh)
(! 749)-> clj -M:1.7
Clojure 1.7.0
user=> (def very-lazy (-> (iterate #(do (print \.) (inc %)) 1)
rest rest rest))
..#'user/very-lazy
user=> (def less-lazy (-> (iterate #(do (print \.) (inc %)) 1)
next next next))
..#'user/less-lazy
user=> (println (first very-lazy))
.4
nil
user=> (println (first less-lazy))
.4
nil
user=>
Yes, iterate
changed:
;; still in the 1.7 REPL
user=> (source iterate)
(defn iterate
"Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
{:added "1.0"
:static true}
[f x] (clojure.lang.Iterate/create f x) )
nil
user=> ^D
Sun Feb 20 13:36:39
(sean)-(jobs:0)-(~/clojure/fresh)
(! 750)-> clj -M:1.6
Clojure 1.6.0
user=> (source iterate)
(defn iterate
"Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
{:added "1.0"
:static true}
[f x] (cons x (lazy-seq (iterate f (f x)))))
So the difference between rest vs. next
is correct in the book but the function they used to illustrate it changed.
And if we look at the changes for Clojure 1.7 https://github.com/clojure/clojure/blob/master/changes.md#changes-to-clojure-in-version-17 we see:
• 2.6 Faster reduce and iterator paths - iterate
- implements IReduceInit
So I expect that's the root cause of the difference.
Thank you, Sean - that's a great help.