Fork me on GitHub
#clojure
<
2020-12-29
>
didibus06:12:12

What happened to clojure.parallel ?

Yehonathan Sharvit10:12:54

In the history of Clojure paper, I read > In addition to the map read/print support, Clojure has a large functional standard library ford ealing with maps, with functions for creating maps (sorted and hashed), associating and dissociating keys with values, merging, lookup, key selection and enumeration, nested map selection and update, sequencing (a seq of a map yields a sequence of key-value tuples), as well as a library implementing relational algebra on sets of maps. Of course, any map library could have these things, but no language at the time had them as pure functions of high-performance persistent HAMTs. In addition, a large subset of the map functions also work on vectors, which are, of course, also associative. What is the library implementing relational algebra on sets of maps that Rich refers to ?

Sergio10:12:35

from the clojure cheatsheet I think is:

Rel algebra	(clojure.set/) join select project union difference intersection index rename
https://clojure.org/api/cheatsheet

Yehonathan Sharvit10:12:54

Nice! That’s exactly what I was looking for.

Yehonathan Sharvit10:12:17

Never noticed that clojure.set provided a bit or relational algebra

Sergio10:12:30

yes, something that can come handy more often from now on

Gleb Posobin06:12:28

@UQN9ESJ00 What do you mean from now on? After discovering that clojure.set includes some relational algebra, or has something happened recently?

Sergio11:12:41

yes, the fact that the relation algebra it’s more powerful than we think at the beginning, quoting Eric Normand: I don’t use these nearly as often as I should, even though I know they’re there https://purelyfunctional.tv/mini-guide/clojure-set/

zackteo11:12:31

Hi guys, does the compile step in clojure ensure that code within an when block is able to execute, even if that path is impossible? For some strange reason, my tests work fine locally but not when it goes through the github CI. https://github.com/zero-one-group/fxl/pull/16 I added a when block so that a block of code skips some tests if resources/credentials does not exist (because the main repo does not have the secret updated yet

delaguardo12:12:32

What do you mean under "able to execute"?

zackteo12:12:10

@delaguardoI keep getting

LOAD FAILURE for zero-one.fxl.google-sheets-test
clojure.lang.Compiler$CompilerException: Syntax error compiling at (zero_one/fxl/google_sheets_test.clj:37:1).
    data: #:clojure.error{:phase :compile-syntax-check,
                          :line 37,
                          :column 1,
                          :source "zero_one/fxl/google_sheets_test.clj"}
     java.lang.IllegalArgumentException: no JSON input found

delaguardo13:12:53

you are checking if file exists and in the same PR you added CI step to create such file

delaguardo13:12:18

.github/workflows/continuous-integration.yml in that file

zackteo13:12:33

Okay ... so hear me out, I got the exact same error from the previous commit as well

zackteo13:12:37

And I was using this as the check (when-not (empty? (slurp "resources/credentials.json"))

delaguardo13:12:38

> Okay ... so hear me out A bit rude ) I checked commit history, you added this CI step in the first commit in that branch

zackteo13:12:56

Sorry I didn't mean to come across as being rude

zackteo13:12:43

Yeap I did add the CI step. So I guess the point is that I have that when because I can't add the secret needed in the main repo yet

delaguardo13:12:46

from exception I can say only that your code is trying to read the file but found not a JSON and as far as I see you have a check for file presence I think you can add a bit more sophisticated check for condition in when to check if file present and valid

zackteo13:12:40

So you are suggesting I might want to combine both checks? 😮

zackteo13:12:28

And apologies again - I was just using > Okay ... so hear me out as a figure of speech. Really do appreciate the help

delaguardo13:12:29

yes, but I can see why this is might be an overkill ) I could also suggest to simply comment out that test until you configure the secret

zackteo13:12:34

I see I see! Yeahhh, i think that makes the most sense

zackteo13:12:34

i also wanted to ask about Clojure's compilation step

zackteo13:12:13

I recall that it won't compile unused code cause of that's characteristic of the underlying jvm

zackteo13:12:04

but I suppose in this case, it might be because the when check depends on an external factor that so I must run the check for it?

zackteo13:12:05

Okay maybe that's perhaps more of google closure and unused vars if anything :thinking_face:

zackteo13:12:40

I think I'll just leave as this for now. Thanks again 🙂

delaguardo13:12:56

when is a macro which expand to (if test (do body)) and if is a special form defined in clojure compiler with a promise to execute only condition and based on result execute one or another branch

zackteo13:12:57

I see I see

didibus10:12:08

When Clojure loads a namespace, it will evaluate all top level forms. Compilation happens at load, and so will also evaluate all top-level forms. And if you perform AOT, it will in turn load everything to compile it ahead of time, and will also thus evaluate top level forms.

didibus10:12:27

What you can do instead is use delay

zackteo10:12:10

And this happens with lein cloverage?

zackteo13:12:38

@U0K064KQV But where do i force/deref it such that that part doesn't become a top level form either?

didibus18:12:25

Yup, it would happen with cloverage as well, when it loads the namespaces all top level will be evaluated

didibus18:12:06

Something like: (defonce service (delay (gs/sheets-service google-props)))

didibus18:12:20

Or: (defonce service (delay (when-not (empty? (slurp "..."))) (gs/sheets-service google-props)))

didibus18:12:05

It does mean everything that uses service now needs to deref service before using it

didibus18:12:56

But it also means that the initialization of service will be delayed to the first read of the var, and no longer run at load time

teodorlu13:12:30

what's an idiomatic name for the constant pi/3? For 2 pi?

zackteo13:12:41

I guess tau is technically 2 pi 😅

😄 3
✔️ 6
teodorlu13:12:43

Noted! How would you name pi/4?

teodorlu13:12:57

from https://clojurians.slack.com/archives/C03S1KBA2/p1609248654055300?thread_ts=1609248390.053200&amp;cid=C03S1KBA22 pi is not defined. • pi/2 is M_PI_22/pi is M_2_PI. So, "_ as implicit /"

akiel15:12:52

Clojure JIRA is constantly reloading for me. Is someone able to get the page working? https://clojure.atlassian.net/jira/software/c/projects/CLJ/issues

Alex Miller (Clojure team)15:12:33

This is a jira bug that has been reported to atlassian

Alex Miller (Clojure team)15:12:56

If you click on a jira issue number rather than a list item that may help

akiel16:12:10

Thanks. I have requested access to Clojure JIRA from my Atlassian account. I hope this is the right way. I found no other way to log in.

Alex Miller (Clojure team)16:12:43

https://clojure.org/dev/dev outlines the contributor process. Note that we typically reserve jira logins for those providing patches

akiel16:12:03

I already contributed to Clojure and I have a small patch for spec2.

Alex Miller (Clojure team)16:12:08

Ok, thanks. What’s the spec 2 issue?

Alex Miller (Clojure team)16:12:57

FYI, core team is all on vacation this week. I will check in at some point but might not be today

akiel16:12:32

No problem. I wish you a happy new year and will come back to you next year.

akiel09:01:09

Hi Alex, thanks for your invitation. Should I file my issue or have you done that already?

Sam Ritchie16:12:12

Hey all! I”m mostly done with a fairly advanced forward-mode automatic differentiation implementation in Clojure - this was fairly subtle, but the implementation is shaping up to be nice and usable outside of my initial goal / library

Sam Ritchie16:12:20

basically this lets you augment a bunch of operations like +, -, *, /, log, exp, etc, and turn them into functions you can “differentiate” through - ie, given some f that uses the new augmented fns, (D f) will return a NEW function that, given an input, returns a measure of how sensitive the result is to that input

Sam Ritchie16:12:16

I wrote it in literate-programming style, so wanted to poll here and see if there was anyone interested in watching / attending a live tour of how to build something like this

Sam Ritchie16:12:39

here’s current status for anyone curious, working great but not quite tidied. Cheers and hope everyone’s doing well over the holidays! https://github.com/sicmutils/sicmutils/blob/81509823023a39553f2f3a5eab7571ab0b986cd6/src/sicmutils/differential.cljc

verma16:12:30

6
1️⃣ 6
🎉 12
athomasoriginal17:12:03

REPL friendly code question. I have the following code:

(defn app
  []
  (create-ring-handler))

(defmethod ig/init-key :system/http-server [_ {:keys [db-spec opts]}]
  (jetty/run-jetty #'app opts))
The above works nicely. I can re-eval all code defined in app (for example, all the handlers) and jetty picks everything up. I would like to pass around a db-spec explicitly now like this:
(defn app
  [db] <--- note db
  (create-ring-handler db))

(defmethod ig/init-key :system/http-server [_ {:keys [db-spec opts]}]
  (jetty/run-jetty #'app opts)) <-- need to pass db-spec to #'app
is it possible to pass runtime params, like db-spec, to the var quoted app in the multimethod? Or maybe i need to restructure more of my code :thinking_face:

seancorfield17:12:08

I would not have expected that first example to work: run-jetty expects a Ring handler function and handlers should always accept the Ring request hash map as their single argument @U6GNVEWQG

seancorfield18:12:19

The usual approach in cases like this is to use middleware to wrap #'app and that middleware accepts the various system information and adds it into the Ring request hash map prior to calling the handler:

(defn wrap-config [h config] (fn [req] (h (assoc req ::config config)))

(defmethod ig/init-key :system/http-server [_ {:keys [opts] :as config}]
  (jetty/run-jetty (wrap-config #'app config) opts))
something like that, maybe? (edited to add config as an arg to wrap-config)

athomasoriginal18:12:57

ooops, yeah, you are correct about the first snippet…I oversimplified my actual code sample too much 😞

seancorfield18:12:59

Note that in the above, once you have started the server, you can't change that middleware without a restart but you can still change the handler.

👍 3
seancorfield18:12:38

You could wrap the middleware call: (jetty/run-jetty (fn [req] ((wrap-config #'app config) req)) opts) -- I think that would work.

athomasoriginal18:12:54

Interesting. I will attempt both of those. Good to know.

athomasoriginal18:12:58

I was thinking in a different way where I was trying to just pass in config to reitit and attach to their :data hash map and that’s what threw me off

athomasoriginal18:12:18

As always, thank you Sean!!

seancorfield18:12:09

Ah, I've never used reitit so I don't know if it has anything to make that sort of handler wrapping easier (nor whether it is REPL-friendly).

athomasoriginal18:12:46

No, not specifically from what I can tell, so your approach is still valid.

euccastro22:12:26

the integrant README has an example setup that would let you reload the middleware too (but you'd have to explicitly suspend and resume; just reloading the handler wouldn't do): https://github.com/weavejester/integrant#suspending-and-resuming

👍 3
euccastro09:01:24

> You could wrap the middleware call: (jetty/run-jetty (fn [req] ((wrap-config #'app config) req)) opts) -- I think that would work I have been trying that with no problem until I started using CSRF protection (i.e. ring-anti-forgery), which needs to maintain state across requests

euccastro09:01:23

you could disable CSRF protection while in development (and I wouldn't rebuild the whole handler on every request in production anyway)

euccastro09:01:52

esp. when using reitit, which IIUC does some sort of "precompilation" of the routes for speed

euccastro10:01:22

another workaround would be to keep a ring session store across handlers (e.g., pass that as part of the config)

verma17:12:56

🎉

51
🎉 9