clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
valerauko 2020-11-21T06:12:54.466500Z

can someone comment on how mixing time bits into an uuid affect its randomness? can you "predict" an uuid generated like this? https://gist.github.com/valerauko/138978741ef9477104eac5796195e61e

dominicm 2020-11-21T14:32:25.018900Z

It's more about your source of randomness. So you'd need to check the details of how uuids are implemented by however you generate them.

dominicm 2020-11-21T14:34:16.019100Z

https://docs.oracle.com/javase/7/docs/api/java/util/UUID.html#randomUUID() uses a cryptographically secure random number generator, for example.

phronmophobic 2020-11-21T07:22:25.468400Z

generally, I don't think uuids are meant to be completely unpredictable. if it's critical to security, then I would probably use some other method.

➕ 1
pez 2020-11-21T08:00:43.481900Z

Good morning! I'm reading Alex Miller's book Programming Clojure. I stumbled some on an example of a function blank? for checking if a string is empty or only has whitespace in it:

(​defn​ blank? [str]
​ 	  (every? #(Character/isWhitespace %) str))
The thing I didn't get was why it also “handles nil and empty cases correctly” as the book told me. I've now checked clojuredocs about it and found the reference to Vacuous truth so I get why it works (and agree that the docs should be updated). I now wonder if not-every? is similar such that I can define not-blank? with it the same way? It seems like it when I REPL it, but I'm on a phone and don't know where/if any isWhitespace method would be defined in JavaScript. I then also noticed that it seems the predicate isn't actually called on empty sequences or nil. And I just would like to hear someone else reason a bit around this whole thing. 😀

2020-11-21T08:15:18.483300Z

Character is a java class, you can't do anything at all with it from clojurescript

2020-11-21T08:16:55.485700Z

In general, books and materials covering clojure cover clojure and not clojurescript and you should not expect the code in them to be valid clojurescript

pez 2020-11-21T08:23:03.487500Z

For the record, I didn't expect that. I just don't have a Clojure REPL handy so I tried to make do with what I have.

pez 2020-11-21T08:34:15.490100Z

I figured out a way to use Replete for this:

(defn not-blank? [s]
 (not-every? #(re-matches #"\s" (str %)) s))

But I'm still curious about the whole vacuous thing. 😎

2020-11-21T08:36:05.492300Z

not-every? Is defined as (comp not every?) so it's truth table is exactly the inverse of every?

pez 2020-11-21T08:38:45.494500Z

Thanks! Being on a phone is not optimal when wondering such things. I guessed that would be the definition.

2020-11-21T08:41:23.496100Z

Like every? corresponds with forall, some corresponds with there exists

2020-11-21T08:42:27.497500Z

So you can turn them into each other by shuffling not arround

pez 2020-11-21T08:44:11.000400Z

some confuses me a lot. Not sure why.

2020-11-21T08:45:03.001200Z

(not-every? f s) => (some (comp not f) s)

pez 2020-11-21T08:49:25.002900Z

Could I define every? using some in a similar way? I'm trying to answer it myself, but I fail...

2020-11-21T08:52:14.006800Z

How do you got from not-every? to every?

2020-11-21T08:53:18.007700Z

I mean, you can work it out as an equation

borkdude 2020-11-21T08:53:41.008700Z

@pez some is like keep but for the first element

2020-11-21T08:54:44.009800Z

If (not-every? f s) = (some (comp not f) s)

2020-11-21T08:56:18.012300Z

And you know not-every? has the inverse truth table to every?, what do you need to do to the left side to turn it into an every?, and then just make sure to do the same thing to the right side

2020-11-21T08:57:35.013400Z

That is the thing with some, it most often not used as a predicate, which can be confusing

pez 2020-11-21T09:15:34.013700Z

(defn my-every? [pred coll]
 ((comp not some) (comp not pred) coll))

❓ 1
pez 2020-11-21T09:26:58.016100Z

There are a lot of examples on some at clojuredocs. Reading them with your hint, @borkdude , really helps!

rgm 2020-11-21T19:14:04.026Z

Does anyone have any favourite open-source code showing how to do background worker threads in a web app? I’m trying to figure out how to do the kinds of things I used to do with Sidekiq in Ruby: send emails, render PDFs, etc. I’m having trouble setting this up reliably with core.async.

borkdude 2020-11-21T19:26:52.027Z

is there an easy way to read an input string using some popup in CIDER / emacs? like (read-line) but more visible for in a demo

valerauko 2020-11-21T19:27:16.027100Z

core.async isn't persistent though so the purpose is a little different

valerauko 2020-11-21T19:27:36.027300Z

there are redis/rdb backed job queues for clojure too iirc

rgm 2020-11-21T19:34:43.031100Z

We’ve been trying to move separate processes along an event log but we’re have some trouble with exceptions killing off a worker and figuring out how best to handle retries, supervision etc. and I’m presuming it’s not necessary for us to reinvent this stuff.

martinklepsch 2020-11-21T21:37:24.032800Z

When working with sets is there a performance difference between these two when checking if a set is empty?

(seq #{1 2 3})   ; is one of these faster?
(first #{1 2 3})

seancorfield 2020-11-21T21:39:50.033600Z

The second one will give a misleading reading if the set contains nil and that happens to be the value you get @martinklepsch

emccue 2020-11-21T21:41:58.033800Z

also just empty? works

emccue 2020-11-21T21:42:45.034400Z

which is implemented via (not (seq ...))

emccue 2020-11-21T21:43:28.035100Z

Though I will ignore this advice in the docstring forever more

emccue 2020-11-21T21:43:32.035400Z

Please use the idiom (seq x) rather than (not (empty? x))

seancorfield 2020-11-21T21:48:11.037900Z

If the argument to first is not already an ISeq, then first calls seq on its argument, so even aside from first potentially giving the wrong answer, it's definitely going to be slower.

emccue 2020-11-21T21:48:53.038300Z

static public Object first(Object x){
	if(x instanceof ISeq)
		return ((ISeq) x).first();
	ISeq seq = seq(x);
	if(seq == null)
		return null;
	return seq.first();
}

emccue 2020-11-21T21:49:30.039Z

all first does is call this method in clojure.lang.RT

emccue 2020-11-21T21:50:16.039700Z

If the seq isn't empty and you get the first element, i know that a lazy-seq might realize 32 elements at that point

emccue 2020-11-21T21:50:27.040Z

so calling .first() might potentially add work

martinklepsch 2020-11-21T21:50:55.040900Z

cool, very interesting

emccue 2020-11-21T21:50:59.041100Z

but besides that, worst case its a second null check

emccue 2020-11-21T21:51:48.042100Z

and direct static method calls - including invokeStatic on clojure.core$first - are the exact kind of thing hotspot can inline if it is hot

emccue 2020-11-21T21:52:07.042400Z

same thing with redundant null checks

emccue 2020-11-21T21:52:57.043200Z

so as per usual, wait til there is a problem and measure - but seq/empty? are what will deal with null elements

emccue 2020-11-21T21:53:54.043600Z

Yeah, so core.async probably isn't your best path

emccue 2020-11-21T21:54:07.044Z

That is made mostly with light interprocess communication in mind

emccue 2020-11-21T21:54:26.044500Z

If you want actual background worker threads, you should use an ExecutorService

martinklepsch 2020-11-21T21:55:30.045700Z

yeah makes sense, I didn’t actually run into any issues, I was just wondering since, yeah converting to a seq seems like a step that may not be necessary, didn’t consider that first would also do that but makes perfect sense

emccue 2020-11-21T21:55:44.046100Z

There are more complete libraries, like quartz, that will have more feature parity with sidekiq

emccue 2020-11-21T21:56:00.046400Z

but for basic stuff, submitting tasks to an ExecutorService is the way to go

emccue 2020-11-21T22:00:20.046600Z

(defn create-background-executor []
  (Executors/newFixedThreadPool 8))

(defn submit-job! [background-executor job]
  (.submit background-executor
           (reify Runnable
             (run [_] 
               (job))))

emccue 2020-11-21T22:01:21.046800Z

Then there are simple enough ways to make a job retry a certain number of times and whatnot

emccue 2020-11-21T22:04:35.047Z

but if you want actual persistent background jobs that will survive a restart and whatnot then something like this might be useful https://www.jobrunr.io/en/

rgm 2020-11-21T22:04:55.047300Z

oh, nice…. thank you. This is another of those areas where coming in to Clojure via ClojureScript has me at a disadvantage, not having ever really worked in Java.

emccue 2020-11-21T22:20:08.047500Z

I don't even remember my learning order, but the Stockholm syndrome of java has definitely set in