Fork me on GitHub
#beginners
<
2021-09-27
>
olaf02:09:41

Hi, how I can serve a static directory index.html, page.html, css/, js/, etc using ring? I searched on google but in the codes found the directory was resources by default or hardcoded. I need to specify the directory when I run the server, something like (serve-dir "dist" :port 3000 :open? true)

practicalli-john06:09:43

Ring middleware wrap-resource to sever html pages from which ever directory you define https://github.com/ring-clojure/ring/wiki/Static-Resources It's typically in resources as that directory is included in the jar (as it's on the class path) when the project is built.

olaf22:09:40

Thanks, what I was looking for. I will probably use wrap-file

John Bradens05:09:39

So I deployed my first basic web app. Any suggestions on how to add some kind of metrics tracking to it so I can see how many page views, session duration, stuff like that? Do people generally just use stuff like mixpanel or are there clojure libraries I should use?

Audrius08:09:40

what is non-lazy for? I need it for side effects like prn or db actions

flowthing08:09:05

(or run!) if you want map-like semantics.

👀 2
tbaldridge20:09:32

I have a need to train a developer in Clojure. What is considered the best Clojure course for a beginner programmer? Preferably something with exercises, that maybe needs input from a mentor every 16 hours of work or so?

lsenjov22:09:07

For our new engineers I did a 2 hour workshop explaining the basics, then gave them brave clojure & the koans. Asked them to read but generally skip the macros part. Worked quite well, had them asking for help about as often as you’re looking for

dabrazhe20:09:10

What's the easiest way to get the epoch for the current week Friday? Eg this week it's smth like [1633046400 "Fri Oct 01 2021"]

schmee20:09:58

with java.time:

ZonedDateTime.now().with(TemporalAdjusters.next(DayOfWeek.FRIDAY)).truncatedTo(ChronoUnit.DAYS).toEpochSecond()
that’s Java code but the same thing can be done with interop in Clojure :)

dabrazhe20:09:44

Hmm, that's a lot of interop : )

dabrazhe20:09:55

how can I translate

with(TemporalAdjusters.next(DayOfWeek.FRIDAY))  
into Clojure code?

schmee21:09:04

like so!

(defn epoch-of-next-friday []
  (-> (ZonedDateTime/now)
      (.with (TemporalAdjusters/next DayOfWeek/FRIDAY))
      (.truncatedTo ChronoUnit/DAYS)
      (.toEpochSecond)))

schmee21:09:31

make sure to import these things in your namespace:

(ns your-ns
  (:import [java.time DayOfWeek ZonedDateTime]
           [java.time.temporal ChronoUnit TemporalAdjusters]))

dabrazhe09:09:17

Thanks! @U3L6TFEJF My solution was to create a range of Fridays with the exact time i need

(take 12 (range 1632441600 18263936000 604800))
Then I find-first date the date in the sequence where it's higher than the current date
(find-first #(> % (quot (System/currentTimeMillis) 1000)) fridays-seq)

Ronny Li20:09:56

Hi everyone, how come I can slurp a file (i.e. (slurp "gcloud_service_account.json")) successfully but when I try to use the following (slurp (io/resource "gcloud_service_account.json")) I get an error?

Execution error (IllegalArgumentException) at app.firestore/eval48272 (form-init17699889922621730434.clj:26).
Cannot open <nil> as a Reader.

alexmiller20:09:57

I'm going to guess from the error that (io/resource "gcloud_service_account.json") returns nil

👍 1
alexmiller20:09:41

resources are loaded from the classpath. if the current directory is not on the classpath, that's not a valid resource path.

Ronny Li20:09:19

ah okay so slurp and resource look in different directories?

dorab20:09:12

slurp is relative to the current dir. resource is relative to any of the items on the classpath.

Ronny Li20:09:40

hm but I put my file in the root directory (same location as project.clj) yet I can do (io/resource "project.clj") successfully

R.A. Porter21:09:01

A resource lookup checks the entirety of the application's classpath.

dorab21:09:06

Are you sure you are getting the same project.clj that is in the root directory? Perhaps you are getting a different project.clj that is somewhere else on the classpath?

👀 1
Ronny Li21:09:57

oh shit @U0AT6MBUL that's it

Ronny Li21:09:37

Any advice for getting io/resource to look in the right path? I'm using CIDER REPL if that changes anything

dorab22:09:14

You just need to make sure that the current directory . is first in the classpath. The default for cider is to use the classpath used when starting up the nrepl process under emacs. If you can explain exactly what you're doing, we can help better. Since you mention project.clj, I presume you're using lein. How are you starting up the nrepl process?

dorab22:09:08

Typically src and possibly resources are the first two directories in the classpath. If that is so, you could consider putting your new file under the resources directory instead of in the root directory.

Ronny Li22:09:49

I just do cider-jack-in from a file within my project. I tried moving the file to src and to resources but no luck 😕

dorab16:09:17

What does your project.clj look like?

dorab16:09:45

From within your cider nrepl bufffer, find out what the classpath is. (System/getProperty "java.class.path") should tell you what is on the classpath.

🙏 1
noisesmith16:09:30

@U01BRM3MQET the reason io/resource doesn't look at the top level of your project is that you don't want to put your entire source tree in your deployed artifact. If you put the file somewhere that gets packages (eg. resources/) you can ensure it will be available via io/resouroce from packaged code

👍 1
Ronny Li16:09:45

thanks everyone. resources/ is in my class path according to (System/getProperty "java.class.path"). I'll have to try moving the file there again and see if it works.

Lukas21:09:44

Hey, I'm trying to implement the microKanren paper and have some troubles to translate from scheme's cons to clojures cons

(defn mplus
  [stream1 stream2]
  (cond
    (fn? stream1) (fn [] (mplus stream2 (stream1)))
    (empty? stream1) stream2
    :else (cons (first stream1) (mplus (rest stream1) stream2)))) 
With clojure this expr. fails (mplus '({'a 1}) (fn [x] 1)) which is basically (cons {'a 1} (fn [x] 1)) while the scheme version (cons '(a . 1) (lambda (x) 1)) evaluates to ((a . 1) . #<procedure (? x)>) My question is, how do I implement the scheme behavior of cons in clojure?

hiredman21:09:01

in the scheme of minikanren cons is a generic pair constructor, it will make a pair out of any two things

hiredman21:09:35

clojure's cons is strictly for constructing sequences, so the second argument must be a seq or nil

hiredman21:09:59

so you cannot use clojure's cons for the same things you can use scheme's cons for

hiredman21:09:32

generally when people want a pair (a tuple, etc) they use a two element vector

Lukas21:09:12

Okay, thanks for the enlightment 🙂

hiredman21:09:34

the streams of (mini|micro)kanren are not disimilar to clojure's lazy-seqs, so you might look at directly representing them that way (there is some trickiness with supporting mplus for interleaved search)

Lukas21:09:53

awesome, thanks again

hiredman21:09:36

and if you are going with microkanren for the minimalist aesthetic you can always represent pairs as closures (fn [a b] #(% a b))

🤯 1