This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-09
Channels
- # announcements (2)
- # babashka (33)
- # beginners (122)
- # bristol-clojurians (1)
- # calva (6)
- # chlorine-clover (3)
- # cider (45)
- # clara (10)
- # clj-kondo (3)
- # cljsrn (17)
- # clojure (80)
- # clojure-dev (21)
- # clojure-europe (86)
- # clojure-italy (5)
- # clojure-japan (5)
- # clojure-losangeles (7)
- # clojure-nl (5)
- # clojure-portugal (3)
- # clojure-uk (31)
- # clojurescript (30)
- # conjure (4)
- # core-async (29)
- # cursive (20)
- # data-science (25)
- # datomic (7)
- # duct (17)
- # figwheel-main (73)
- # fulcro (23)
- # jobs-discuss (36)
- # juxt (5)
- # kaocha (2)
- # lambdaisland (6)
- # luminus (5)
- # malli (17)
- # mount (10)
- # music (7)
- # off-topic (16)
- # re-frame (30)
- # ring (17)
- # rum (1)
- # shadow-cljs (10)
- # spacemacs (10)
- # specmonstah (4)
- # sql (45)
- # tools-deps (21)
- # xtdb (20)
Hello, people. I have a thread running a loop/recur (it's a Kafka consumer). That thread is launched from a call to component/start
, and I want to stop that thread (break the loop) whenener component/stop
is called. What would be the best way to do this? A hack is to create an atom that is a boolean, and check it before calling recur
. It works but I want to avoid global state. If the question is not clear, I can create a gist and share it. Thank you.
@yokoyama.km You can try calling future-cancel
on it but the loop would need to be "well-behaved" and be able to be cancelled.
Be sure to wait on the future in your stop, so he future has actually exited by the time it returns
Yeah, that would be my recommendation too: provide some mutable state that can be leveraged to cause the thread to stop. At work we do something similar (but the other way around) -- we wait on a promise in our main thread and the background thread running the server delivers the promise when it shuts down.
Thank you, guys. I was thinking that could exist some way involving channels, but I didn't come up with a solution.
an alternative to an atom
(designed for arbitrary and async update from N threads) is a promise
or delay
(designed to start "uninitialized" and then to be initialized exactly once)
this can give you the same behavior (call realized?
to find out if its been initialized, if so you know its time to exit) while clarifying intent (this isn't a mutable box that gets switched around multiple times, it's a one time one way switch)
you can use a promise-chan for the same purpose, but if you aren't already using core.async this isn't worth bringing it in
Thank you too, @U051SS2EU. Could you extend the explanation on using promise-chan? My issue with using channel is that it blocks on receiving from an empty channel, right?
poll!
returns immediately in all cases, nil
if there was no value, the value on the chan otherwise
a promise chan will start blocked (returning nil on every poll! call) then switch permanently into unblocked (returning the same value for every poll! call)
but really it isn't doing anything a bare promise
wouldn't do, and if you aren't using eg. alts!
already it's added complexity with no benefit
Oh, I see. So I'll try first make promise
and realized?
work. Thank you again.
the third function there is deliver
(that turns the one way switch to realize the promise)
Yes, sure. Thank you
number_to_human(123) # => "123"
number_to_human(1234) # => "1.23 Thousand"
number_to_human(12345) # => "12.3 Thousand"
number_to_human(1234567) # => "1.23 Million"
number_to_human(1234567890) # => "1.23 Billion"
Is there something similar in Clojure or Java? It seems like a pretty common task but I couldn't find anything similar yethello @nfedyashev https://github.com/trhura/clojure-humanize seems to be what you are looking for
you can also do this with clojure.pprint/cl-format
without any external library
(ins)user=> (clojure.pprint/cl-format nil "~r" 12)
"twelve"
(ins)user=> (clojure.pprint/cl-format nil "~r" 1234567890)
"one billion, two hundred thirty-four million, five hundred sixty-seven thousand, eight hundred ninety"
not quite what you want I guessit implements the format from common lisp, which is extensively documented online (I think someone wrote a whole book on that one function)
A bit surprising to know that cl- stands for Common Lisp.. I have never seen this before. Referencing to another lang pattern/convention from the core functions
Hi, are there any clj source code formatter that format something like
(let [foo "foo"
barqux "barqux"]
....)
into
(let [foo "foo"
barqux "barqux"]
....)
if you are using emacs clojure mode support this: https://github.com/clojure-emacs/clojure-mode/#vertical-alignment
NaN is weird in so many ways, in multiple programming languages. This Github repo is not actually recommended, unless you are somewhat obsessive-compulsive about such things: https://github.com/jafingerhut/batman
Is there an opposite to destructuring? For example I often have to write {:a a :b b}
and I guess a macro could save me from the repetition. Wondered if someone already wrote it?
I defined a keyboard macro in my IDE. I type ==TAB
and then whatever I type appears twice, with a colon in front of the first one
==TABfoo
=> :foo foo
Nice trick :)
Several libraries have something similar @neo2551 including one of ours...
https://github.com/worldsingles/commons/blob/master/src/ws/clojure/extensions.clj#L152-L174 for example
Thanks I will look for it then.
there are a few ways to do it - I have this for debugging:
(ins)user=> (defmacro locals [] (into {} (map (juxt keyword identity) (keys &env))))
#'user/locals
(ins)user=> (let [a 0] ((fn [x] (loop [q :a] (locals))) 42))
{:a 0, :x 42, :q :a}
Per the docstring of local-map
in our library: Inspired by an example from @U051SS2EU on Slack. 🙂
(demonstrating it captures all varieties of local binding)
there's a version in the useful
lib too
Thanks a lot!
because somebody else required clojure.string first
common gotcha - pprint will get loaded by default repls, won't load when running your app
string may or not preload
> common gotcha - pprint will get loaded by default repls, won’t load when running your app ooh, that’s sneaky
best practice (outside a repl at least) is to always require and alias every ns you actually access
Hey team, is there a "best practices for setting up clojure with postgres" tutorial you'd recommend? (am looking for recommended libraries, potential ~orm-like stuff, discussion on tradeoffs between diff choices) If something like this exists would love to know!
@stopachka We don't use "ORM" stuff because we don't have objects. next.jdbc
is going to be your first stop -- that's a general JDBC wrapper and lets you read/write hash maps from/to rows in the database.
Start here: https://cljdoc.org/d/seancorfield/next.jdbc/1.1.547/doc/getting-started -- read all the docs (seriously!)... there's some PostgreSQL-specific stuff in the Tips & Tricks page but the rest should all be generally applicable.
I test against Embedded PostgreSQL 12.2.0 but you'll want the regular JDBC driver org.postgresql/postgresql {:mvn/version "42.2.14.jre7"}
There's a #sql channel if you have questions.
nice! one quick q, am guessing there may also be libraries that do stuff like: 1. something that handles migrations, etc 2. maybe a macro library, that given some sql structure, gives me a bunch of helper functions for querying 3. some higher-level sql library, so we don't need to write with strings perhaps 2 & 3 are a bit superfluous -- wonder how clj community handles these
There are https://github.com/weavejester/ragtime and https://github.com/yogthos/migratus for 1. There's https://github.com/seancorfield/honeysql for 3 (and a bit of 2).
Because you mentioned postgres, also check out https://github.com/nilenso/honeysql-postgres for an example of extending honeysql.
I'd recommend Migratus for migrations and I'll recommend HoneySQL too (but, caveat, I maintain that as well as next.jdbc
). And, yes, the PG extensions to HoneySQL are worth looking at.
There's a #honeysql channel if you need it. Also, if you want to keep your SQL out of your code (some folks prefer that approach), there's #hugsql -- which has a built-in adapter for next.jdbc
(and there's a quick start guide for HugSQL in the next.jdbc
docs).
I just noticed that you can't call pop
on a LazySeq, even after calling doall
. I have some code that operates on a list as if it were a stack, but there are times when I also must map
down the "stack" (I know that is technically a violation of the stack API) and still be able to call pop
on the resulting seq. Any suggestions?
The only solution I have come up with is (pop (reverse (into '() (map identity '(1 2 3)))))
but I don't like needing the reverse.
I suppose I could switch to using rest
instead of pop
and get the same result except it remains as a LazySeq. Is that good/bad? I would rather have an efficient way to create a list
from a LazySeq that doesn't reverse the order.
@erp12 Use a vector instead? And mapv
instead of map
.
or vector and transduce
why do you need a list?
why is pop better than rest for your use case?
(agreed, for a stack, use a vector, if that's what you need)
lists are faster than vectors for this
but not if you turn them into seqs
oh, so this might actually be the rarely seen use for list*
user> (pop (list* (map inc (range 5))))
Execution error (ClassCastException) at user/eval140786 (form-init377868074523440121.clj:18).
clojure.lang.ChunkedCons cannot be cast to clojure.lang.IPersistentStack
np - I should have mentioned that here as well
as the doc string says "Creates a new seq ..."
if you're going to use stack verbs then I'd stick with stack api
I went with lists because of the note here: https://clojure.org/reference/data_structures#Lists
well that's fine until you do non-stack things
@erp12 cool - sounds like an actual list is what you want, see the list*
function linked on that same node
it gives you a real list without reverse etc.
that sounds worse than using a vector to me
n/m it doesn't return a list
Thanks all! The only time I needed to map
down the stack is to coerce the elements in the event stack is being passed from the outside. That might happen rare enough to accept the cost of a round trip through a seq, or maybe I will just check the stack with a spec and then throw if the caller screwed it up.
Hello clojurians, I was wondering if this is a correct way to use a repl a running ring webserver:
(defn -main
"Blogo blog backend"
[]
(future ;; Pretty cool, it unblocks me from using the repl!!
(jetty/run-jetty app {:port 9091})))
It fixed my problem - when I run (-main) in the REPL I can still evaluate expressions in it, otherwise it somehow stops working correctly. I think this leaves me two threads - one for ring and one for me.Passing :join? false
in that options hash map will do what you want for the REPL.
But if you do it in your -main
, when you run the app outside the REPL, it will just exit immediately.
So I'd recommend writing a function to call specifically from the REPL, and then calling it from -main
with a different argument:
(defn start [& [join?]] (jetty/run-jetty-app {:port 9091 :join? join?}))
;; call from REPL as (start)
(defn -main [& args ]
(start true))
@dimitar.ouzounoffThanks! I just tried it out, works for me :)
but what do you think of using future like that if ring didn’t had :join? ?
It will mean your -main
will just exit when you run it from the command line -- which is not what you want.
It also means you won't be able to stop the server within your REPL either.
run-jetty
should return a handle for the server, that you can call .stop
on.
See this code https://github.com/seancorfield/usermanager-example/blob/develop/src/usermanager/main.clj#L140-L175 which has logic to start/stop either Jetty or http-kit (so it's a bit more complex that what you're doing).
It captures the result of calling (jetty/run-jetty app {:port ... :join? false})
so that it can .stop
it later.
http-kit works differently -- it starts in the background anyway, and returns a handle to the server that you invoke with no args to stop it.
Another reason not to use future
like that is that if the server throws an exception, you won't see it -- the process inside the future
will just silently die.
You only see the failure if you deref the future -- when it will throw the exception that the process failed with.
thanks! Usermanager is just I was looking for - I wanted to read some clojure example code like this.
you can refer to the last value with *1
, you can use arrow keys if you use a repl with readline capability (like clj
from the clojure team, or lein repl
from the lein project)
IIRC you can use M-p in emacs to bring up the previous input
but this is going to be different for every UI and isn't built into clojure itself
https://corfield.org/blog/2019/09/13/using-spec/ talks about how we use Spec at World Singles Networks. We've been heavy users since the 1.9 alpha days.
Thanks for writing this, I really needed to read it.
Thanks @seancorfield