clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
zhuxun2 2021-05-06T06:06:04.109Z

If I have

(defn my-func []
  (async/<!! (async/timeout 100000)))

(async/go (my-func))
I assume my-func is going to be executed in one of the pooled threads, right? In that case, is the <!! going to be blocking or parking?

raspasov 2021-05-06T07:09:58.109900Z

This is not very good. You’re blocking inside a (go …) macro. You should do something like:

(defn my-func []
  (async/<!! (async/timeout 100000)))

(async/go (async/<! (async/thread (my-func))))
That way my-func will run outside of the fixed thread pool dedicated to (go …) macros.

raspasov 2021-05-06T07:12:12.110200Z

It’s one of the core.async gotchas that’s not immediately obvious.

2021-05-06T20:28:31.195900Z

It's going to block the thread. That's why the doc for <!! says: > Not intended for use in direct or transitive calls from (go ...) blocks. Use the clojure.core.async.go-checking flag to detect invalid use (see namespace docs).

2021-05-06T20:30:22.196100Z

You should never use a blocking take/put or any other blocking operations inside a go block, even transitevely through a function called inside it.

2021-05-06T20:31:46.196300Z

And you should never have a go block that doesn't do a parking operation directly in it. So in your case use async/thread instead.

2021-05-06T20:38:52.196500Z

I also don't think the way @raspasov showed is ideal, instead of:

(defn my-func []
  (async/<!! (async/timeout 100000)))

(async/go (async/<! (async/thread (my-func))))
You simply want to do:
(defn my-func []
   (async/<!! (async/timeout 100000)))
 
(async/thread (my-func))
Wrapping this further in a go block serves no purpose and slows things down.

raspasov 2021-05-06T21:03:16.200800Z

@didibus sure, there’s many ways you can go about this depending on what you want to achieve; I just tried to show an OK way to connect a (go …) block with something that’s blocking via (<!! …)

niwinz 2021-05-06T06:22:35.109600Z

<!! is always blocking

Ben Sless 2021-05-06T06:45:49.109700Z

I always wandered how that interacts with direct linking and aot compilation. Anything I should be wary of?

🤷 1
restenb 2021-05-06T08:47:43.112800Z

to you web stack gurus that I know lurk in here; I have a server giving me HTTP 500: Request timed out occassionally on long-lived requests. where could this be coming from? I have not implemented or configured any timeouts that I know of, and I would expect to see HTTP 408if it was timed out due to, well, too much time passing.

restenb 2021-05-07T10:08:46.202500Z

@jumar Thank you! This is exactly the information I was looking for. 🙂

flowthing 2021-05-06T08:48:23.112900Z

Your HTTP proxy (Apache or Nginx or similar) would be my guess.

restenb 2021-05-06T08:49:27.113100Z

it's jetty, but yes, it probably is. just can't figure out why or what I could possibly do about it

p-himik 2021-05-06T08:49:30.113300Z

If you can confirm that it's your server and not some proxy, then set up a proper logging that will show where that error is coming from. With a proper setup, such questions are answered by the lots 100% of the time.

p-himik 2021-05-06T08:50:03.113500Z

If it's a proxy that you control, same thing - look into its logging setup.

restenb 2021-05-06T08:50:43.113700Z

well, it's an azure app service, so no I don't have "direct" control of jetty, but there may still be logs somewhere

restenb 2021-05-06T08:51:37.113900Z

the timing of the drops also differs some over time (seems to be 5-6-7 minutes), so it doesn't look like a set timeout to me

restenb 2021-05-06T09:03:03.114100Z

I guess it's possible that Azure doesn't want long-lived requests and it's my job to design around that 🙂

mloughlin 2021-05-06T11:53:26.116300Z

If I want to follow the "Cryptographic Right Answers" in clojure, which libraries should I be looking at for e.g. symmetric encryption and hashing?

mloughlin 2021-05-06T11:54:46.116800Z

(assuming I know nothing about the Java ecosystem)

rutledgepaulv 2021-05-06T11:59:17.117100Z

lvh / latacora are good places to look for advice. https://www.lvh.io/posts/cryptographic-right-answers/ https://www.lvh.io/posts/crypto-apis-and-jvm-byte-types/ . That said, the defacto standard in the java ecosystem is a set of libraries under the bouncy castle umbrella

borkdude 2021-05-06T11:59:43.117400Z

buddy is used a lot for this

borkdude 2021-05-06T11:59:50.117600Z

which is based on bountycastle

ghadi 2021-05-06T12:06:02.118100Z

would try to avoid buddy if at all possible

ghadi 2021-05-06T12:06:37.119100Z

Swiss army knife design of crypto libraries is a security antipattern

👍 1
mloughlin 2021-05-06T12:09:31.119400Z

direct interop is the way to go?

ghadi 2021-05-06T12:10:28.120500Z

you could look at lvh’s libsodium wrapper (caesium) or google’s Tink

👍 2
rutledgepaulv 2021-05-06T12:10:33.120800Z

Lvh's caesium (clojure lib) is likely worth looking at if you're doing a lot of crypto

ghadi 2021-05-06T12:11:27.122400Z

If you’re just hashing, direct interop is fine. If you need encryption like AEAD then use something like Tink or libsodium

ghadi 2021-05-06T12:12:07.123300Z

Basically for encryption you want to use something that doesn’t expose nonce management to the user

mloughlin 2021-05-06T12:12:19.123700Z

yes, that's what I'm looking for

ghadi 2021-05-06T12:12:41.124300Z

Try Tink

mloughlin 2021-05-06T12:13:42.124600Z

at $previousJob we were using a version of .NET that didnt have AES-GCM implemented and had to cobble together some kind of AES-CBC + HMAC monster which never felt correct. I'll give Tink a look, thanks

ghadi 2021-05-06T12:14:45.125400Z

(Of course you can do it all with interop, too)

NoahTheDuke 2021-05-06T12:44:34.132Z

@ghadi you said something about staying away from buddy. wanna go into more details? We use it in my current project and I’d like to avoid any issues

yuhan 2021-05-06T12:47:12.133400Z

I was surprised to find out that split-with is literally implemented as [(take-while pred coll) (drop-while pred coll)], meaning that it does a redundant amount of work applying the predicate twice for every element that satisfies it. See how the following takes 800+ ms and prints 0 1 2 3 0 1 2 3

(time
  (mapv doall
    (let [xs   (range 10)
          pred #(do (println %) (Thread/sleep 100) (&lt; % 3))]
      (split-with pred xs))))
I've always assumed it was doing something to optimize away the redundant applications, is there any reason it's not implemented in a more efficient manner? Surely the semantics won't be violated if we assume referential transparency and only evaluate each element once.

☝️ 1
borkdude 2021-05-06T12:48:28.134200Z

@qythium I'm sure Alex welcomes an http://ask.clojure.org item for this which could lead to a JIRA ticket, which could lead to a patch, which could lead to a better Clojure future 🎉

2021-05-06T12:48:48.134600Z

If pred calculates hard, it make sence

rutledgepaulv 2021-05-06T12:50:41.135800Z

Changing it would break stateful predicates (not that I know of anyone relying on the number of executions of a predicate for split-with)

yuhan 2021-05-06T12:51:04.136300Z

Yep I'll post this on http://ask.clojure.org too, just wondering as it seems like such a glaring oversight

2021-05-06T12:52:27.138700Z

If your code depends on stateful predicates, relying on 2 times eval of them, possibly you are doing something wrong 🙂

rutledgepaulv 2021-05-06T12:52:48.138900Z

I don't disagree. Just saying it's a possibility :)

✅ 1
yuhan 2021-05-06T12:53:27.139600Z

@rutledgepaulv I was thinking about that too, but if anything I'd expect (apply concat (split-with pred xs)) == xs to always hold

yuhan 2021-05-06T12:54:13.140600Z

and here's that expectation being violated:

(let [xs      (range 10)
      counter (atom 1)
      pred    (fn [x] (&lt; x (swap! counter + 1/2)))]
  (split-with pred xs))
;; =&gt; [(0 1 2) (7 8 9)]

2021-05-06T12:54:27.140900Z

Oh, looks like Functor/Monad laws in the begining ))

2021-05-06T12:55:06.141400Z

But yes, Clojure has implicit side effects

2021-05-06T12:59:03.143200Z

But this is not a bad thing, just keep it in mind and don't step on this emergent area - like relying on order of function arguments evaluation etc.

2021-05-06T13:04:48.145700Z

There are more interesting things and leaky abstractions - when -&gt; does not equal to as-&gt;

ghadi 2021-05-06T13:06:18.146800Z

non-crypto expert users cut themselves when using crypto libraries with tons of choices

yuhan 2021-05-06T13:06:26.147Z

it was tricky trying to "couple" the two return results together while preserving laziness, but here's my attempt:

(defn split-with*
  "Like `split-with` but evaluates `pred` at most once on each element"
  [pred coll]
  (let [takes (take-while pred coll)
        drops (lazy-seq (drop (count takes) coll))]
    [takes drops]))
Probably there's a better solution using something like volatiles

ghadi 2021-05-06T13:06:34.147100Z

buddy is one such library, so is bouncy castle

ghadi 2021-05-06T13:07:26.148200Z

search for the rationale on Google's Tink and other high-level crypto APIs

2021-05-06T13:07:31.148500Z

Of course, at least not to count takes

NoahTheDuke 2021-05-06T13:07:32.148600Z

Interesting! I’ll read through that. Thanks for the link

ghadi 2021-05-06T13:07:37.148800Z

"misuse-resistance" is a general topic in crypto

NoahTheDuke 2021-05-06T13:07:56.149400Z

Yeah that makes total sense

yuhan 2021-05-06T13:08:41.150800Z

Do you have any examples of this? Just curious

2021-05-06T13:08:44.151100Z

Especially if pred allways true and takes have to be infinite and lazy )

ghadi 2021-05-06T13:09:22.151700Z

unzipping into two sequences is not such an easy problem after all 🙂

ghadi 2021-05-06T13:09:36.152Z

but then again most predicates don't have a Thread/sleep call in them

2021-05-06T13:10:31.152800Z

They can query http requests 🙂

ghadi 2021-05-06T13:10:49.153200Z

maybe that's not such a great idea

2021-05-06T13:12:00.154500Z

Yep, but we discussing about possibilities

yuhan 2021-05-06T13:12:05.154700Z

I don't know, I use split-with on some pretty expensive predicates (eg. graph traversal to find common ancestor)

2021-05-06T13:15:37.156600Z

Of cousre, but for now in Russian video only https://youtu.be/0JAHb35QOYQ?t=781

Christoffer Ekeroth 2021-05-06T13:34:01.157300Z

Sounds reasonable - Heroku kills any request that’s longer than ~1 minute IIRC

Christoffer Ekeroth 2021-05-06T13:38:40.157600Z

In general, I would consider HTTP requests longer than a few seconds an antipattern, but if you can’t control the server there’s not much you can do about it I guess. The “proper” solution would be to perform the task asynchrounously (e.g. by putting it on a queue) and then poll the status of the task / set up a websocket or long-polling subscription that notifies the client when the task is complete

2021-05-06T13:39:29.158800Z

(defn sp-with [p coll]
  (-&gt;&gt; coll
       (map p)
       (map vector coll)
       (split-with second)
       (mapv #(map first %))))

2021-05-06T13:40:37.160900Z

Hardweight predicate evaluates once. But beware stateful predicates and chunked implementations of lazy-seq functions.

2021-05-06T13:40:53.161300Z

I'm trying to create a Docker image for arm32v7 (RaspberryPi). Can anybody confirm that the official Docker images (https://hub.docker.com/_/clojure/) are not built for arm?

2021-05-07T07:26:48.201900Z

Agreed. My Dockerfile for x86 is actually using the Clojure image as a build target, then building the final container from it to just run on a jdk-alpine image.

javahippie 2021-05-06T13:45:10.162200Z

The docs on that page link to this for arm: https://hub.docker.com/r/arm64v8/clojure/

2021-05-06T13:51:37.162400Z

Yes, I'm sorry I wasn't clear enough. I really need images for arm32v7, as the Raspbian image I'm using is 32bit.

2021-05-06T13:53:08.162600Z

And unfortunately, the images for this platform are two years old (https://hub.docker.com/r/arm32v7/clojure/tags?page=1&amp;ordering=last_updated).

javahippie 2021-05-06T13:58:09.162800Z

You could try updating/changing the underlying Dockerfiles, but from the official support docs it looks grim for out-of-the-box images, I agree

2021-05-06T14:06:19.163100Z

Yes, that sounds like the quickest route to go

jumar 2021-05-06T15:28:05.163300Z

IIRC azure app service has this timeout enforced. They say 230 seconds here: https://social.msdn.microsoft.com/Forums/en-US/05f254a6-9b34-4eb2-a5f7-2a82fb40135f/time-out-after-230-seconds?forum=windowsazurewebsitespreview

2021-05-06T15:44:59.163500Z

Something to keep in mind is those are "official" in the sense that http://docker.com calls it official, not in the sense that anyone from the clojure dev team has had anything to do with it

2021-05-06T15:53:03.163700Z

I say that because those images are not really images for running clojure programs, they are images for building clojure programs, which is why they include variants that include, basically, different clojure build tools

💯 1
2021-05-06T15:54:23.163900Z

If you are looking for an image to run a clojure program by far the way to do that is by building an uberjar outside of docker, then use a jdk docker image to the uberjar

2021-05-06T17:23:24.167700Z

I'm looking at clojure.core.logic.fd and wishing for a version that can do... less logic programming and more constraint solving/optimization on rationals. I have a set of producers that can produce two things in any ratio, and a demand for each thing. I want to give a bag of constraints like:

(&lt;= supply-1 demand-1)
(&lt;= supply-2 demand-2)
(&lt;= supply-3 demand-3)
(&lt;= (+ supply-1 supply-2) producer-capacity-A)
(&lt;= (+ supply-1 supply-3) producer-capacity-B)
and have it optimize for the smallest unsatisfied demand (hopefully but not necessarily 0)

2021-05-06T17:23:52.168300Z

does anything like that exist? I'm new to logic and constraint solving and don't know what to search for.

phronmophobic 2021-05-06T17:36:25.168400Z

For solving/optimizing linear programming problems, I might look for something besides core.logic. There's some clojure wrappers of constraint solvers: • https://github.com/levand/prolinhttps://github.com/tanders/clojure2minizinc/ It might also be worth finding a good linear constraint solver in java

vncz 2021-05-06T17:39:30.168900Z

Does anybody have any suggestion on how to call the function? Ideally I would call it 412 so I could just do (responses/412 "Error") but it’s not possible; I am not very convinced about r412 or generally speaking r{status-code}

vncz 2021-05-06T17:39:50.169Z

flowthing 2021-05-06T17:40:38.169100Z

precondition-failed?

2021-05-06T17:41:13.169300Z

yeah, http status codes all have textual descriptions

flowthing 2021-05-06T17:41:19.169500Z

https://httpstatuses.com/

vncz 2021-05-06T17:41:32.169800Z

Hmm, good point, I could just use textual names

flowthing 2021-05-06T17:41:46.170Z

Also, as a precedent, all ring.util.response fns are named like that (https://ring-clojure.github.io/ring/ring.util.response.html).

Dane Filipczak 2021-05-06T17:42:33.170200Z

I second looking into minizinc, which can be run from clojure via http://jacop.osolpro.com/.

Joel 2021-05-06T18:18:43.173900Z

I find I have this pattern too often, I'm curious how to make this cleaner. I have some data, I want to "compile" it, then i want to use the compiled version, but still want to access the data, eg:

(def myregex "x.*x")
(def pattern (Pattern. myregex))

(defn where-pattern-used []
   (...))

Would a let statement know to not keep compiling the regex?
Not looking for something specific to regex, this is generally question for newbie.

2021-05-06T18:19:31.174400Z

why do you think it keeps compiling the regex?

Joel 2021-05-06T18:20:00.175100Z

above, i don't think it would, but I find it awkward to use (def's) for so many of these.

2021-05-06T18:20:08.175400Z

ah

2021-05-06T18:20:36.176500Z

I see so that is an example of your work around, not an example of what you are trying to work around

2021-05-06T18:21:00.177200Z

defs of values are good

Joel 2021-05-06T18:21:07.177500Z

yeah, seems like "littering" of def's to get around a specific problem.

2021-05-06T18:21:19.177800Z

it isn't

Joel 2021-05-06T18:22:03.178100Z

seems like it could be localized better.

2021-05-06T18:22:19.178400Z

why should it be localized?

2021-05-06T18:22:32.178600Z

do you localize the number 5?

2021-05-06T18:25:17.180700Z

if something is a value, has no state, is freely shareable, then def'ing it is good

Joel 2021-05-06T18:29:57.180900Z

i suppose there's something like:

(defn compile [data] {:data data :compiled (compiled data) })
(def dc (compile "something"))

Joel 2021-05-06T18:30:17.181400Z

What I'm asking really is what are my options here, not "no, def is cool man"

alexmiller 2021-05-06T18:31:05.181800Z

re-pattern is a thing (vs Pattern.) btw

2021-05-06T18:35:24.182300Z

you may want to look at some kind of programatically built pipeline

2021-05-06T18:36:54.183800Z

e.g. you start with a map like {:a 1 :b 2} and have another map that says something like {:c {:depends [:a :b] :f +}} and some function f that given those two maps produces {:a 1 :b 2 :c 3}

2021-05-06T18:38:33.184800Z

https://github.com/plumatic/plumbing#graph-the-functional-swiss-army-knife is the first place I saw that pattern in clojure, but it is kind of old hat by now so there may be some more recent libraries for it, and it isn't too hard to just build it yourself

Joel 2021-05-06T18:40:52.186900Z

interesting @hiredman that might be generally useful for me. @alexmiller wasn't trying to solve regex, just general understanding... i thought maybe function inside of a let... but i you can't call those functions.

2021-05-06T18:41:25.187500Z

https://gist.github.com/hiredman/71b71e4e07e7666fe1b9def9a476c765 is an example of what it takes to write that kind of thing yourself (it has the additional wrinkle of doing everything via map instead of just calling functions)

Joel 2021-05-06T18:46:41.189300Z

But is "fred" called every fn call?

(def constant "stuff")
(defn x [data] (let [one-or-every-time (compile constant)] ... )

2021-05-06T18:47:54.190100Z

in the graph/pipeline stuff I mentioned, all the results are cached in the map

2021-05-06T18:48:20.190700Z

and if some key depends some other keys, those keys are computed first and cached in the map

2021-05-06T18:49:05.191400Z

https://www.microsoft.com/en-us/research/uploads/prod/2018/03/build-systems.pdf is a good, but much deeper dive in this kind of thing, in a slightly different context

2021-05-06T18:51:08.192800Z

these kind of systems where you have a sort of computational graph with dependencies and you want to build each node in the graph once and re-use it are like a build system like make

2021-05-06T19:01:51.194100Z

Gurobi is commercial, but has much cheaper licenses for educational institutions, e.g. colleges. It can do linear constraint optimization and mixed integer/linear optimization. I am sure there are open source tools with a lot of overlapping functionality -- Gurobi seems to go the extra mile in terms of taking advantage of multiple cores and/or physical machines, if you ask it to.

Joel 2021-05-06T19:39:27.195400Z

i this should work? Meaning that (compile to-compile) will only be invoked once?

(def to-compile "...")
(def my-fn-compiled []
    (let [compiled (compile to-compile)]
    (fn [data] (evaluate compiled data))

2021-05-06T20:42:48.197600Z

I can imagine code doing so, they probably had to account for the two-time eval, and it would probably have been easier for them to do a one time eval.

2021-05-06T20:43:28.198600Z

In that expression (compile to-compile) would only be invoked once regardless of whether you use that, or (compile "...") , not because of the first def, but because the last expression is a def. If you reload the file, it will be re-evaluated of course, but I'm guessing that when you say "will only be invoked once", you mean once per time the form is evaluated.

2021-05-06T20:45:28.199400Z

In a situation like that, some people will write the code like this instead:

(def to-compile "...")
(let [compiled (compile to-compile)]
  (defn my-fn-compiled [data]
    (evaluate compiled data)))

2021-05-06T20:45:58.200100Z

Note that in your code snippet, the [] after my-fn-compiled will be ignored, because it is def my-fn-compiled, not defn my-fn-compiled

2021-05-06T20:52:45.200200Z

What exactly you're trying to do? You don't want compile to re-evaluate for the same data more than once? If so, you can use memoize:

(def compile
  (memoize
    (fn [data]
      {:data data :compiled (compiled data)})))

2021-05-06T20:55:11.200400Z

Another option if you want to only reuse some evaluations of it without def, so assuming you want to do so only locally, just use a Closure:

(let [dc (compile "something")]
  (defn foo
    []
    (doSomething dc)))

2021-05-06T20:58:21.200600Z

That's basically the three options you have. Either cache it in a def, or cache it in a Closure with let, or memoize it.

2021-05-06T22:08:02.201100Z

are you re-using that function? If not, maybe just keep it anonymous as the code is more clear then the name.