Fork me on GitHub
#clojure
<
2020-11-21
>
valerauko06:11:54

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

phronmophobic07:11:25

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
dominicm14:11:25

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.

dominicm14:11:16

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

pez08:11:43

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. 😀

hiredman08:11:18

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

hiredman08:11:55

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

pez08:11:03

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.

pez08:11:15

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. 😎

hiredman08:11:05

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

pez08:11:45

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

hiredman08:11:23

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

hiredman08:11:27

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

pez08:11:11

some confuses me a lot. Not sure why.

hiredman08:11:03

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

pez08:11:25

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

hiredman08:11:14

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

hiredman08:11:18

I mean, you can work it out as an equation

borkdude08:11:41

@pez some is like keep but for the first element

hiredman08:11:44

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

hiredman08:11:18

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

hiredman08:11:35

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

pez09:11:34

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

1
pez09:11:58

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

rgm19:11:04

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.

valerauko19:11:16

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

valerauko19:11:36

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

rgm19:11:43

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.

emccue21:11:54

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

emccue21:11:07

That is made mostly with light interprocess communication in mind

emccue21:11:26

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

emccue21:11:44

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

emccue21:11:00

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

emccue22:11:20

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

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

emccue22:11:21

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

emccue22:11:35

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/

rgm22:11:55

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.

emccue22:11:08

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

borkdude19:11:52

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

martinklepsch21:11:24

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})

seancorfield21:11:50

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

emccue21:11:58

also just empty? works

emccue21:11:45

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

emccue21:11:28

Though I will ignore this advice in the docstring forever more

emccue21:11:32

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

seancorfield21:11:11

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.

emccue21:11:53

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();
}

emccue21:11:30

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

emccue21:11:16

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

emccue21:11:27

so calling .first() might potentially add work

martinklepsch21:11:55

cool, very interesting

emccue21:11:59

but besides that, worst case its a second null check

emccue21:11:48

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

emccue21:11:07

same thing with redundant null checks

emccue21:11:57

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

martinklepsch21:11:30

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