Fork me on GitHub
#beginners
<
2021-07-16
>
Edward Ciafardini10:07:28

I find myself using "(require '[clojure.string :as str])" in the REPL a lot. Is there a way to configure clj or lein repl to run this on startup?

Geoffrey Gaillard10:07:50

I don’t know if it’s idiomatic, but this works:

$ clj -e "(require '[clojure.string :as str])" --repl
user=> (str/upper-case "a")
"A"

seancorfield15:07:24

@U01TLNH6ULD Another option is to have a user.clj file on your classpath (usually in a dev folder which is only added to the classpath via an alias/profile) and have it do that require:

(! 521)-> cat dev/user.clj 
(ns user (:require [clojure.string :as str]))
(! 522)-> cat deps.edn 
{:paths ["src" "resources"]
 :aliases
 {:dev {:extra-paths ["dev"]}}}
(! 523)-> clj -A:dev
Clojure 1.10.3
user=> (str/trim " x ")
"x"
user=> 

seancorfield15:07:59

Clojure itself automatically loads the user ns at startup, so it will load a user.clj file if present.

Edward Ciafardini21:07:10

How do I access the classpath on a Mac? I found these instructions: "Go ahead and open the *~/.profile* and make sure that the PATH variable is set and includes */usr/local/bin* and */usr/local/sbin*. You should have a line in the file that looks similar to the following, if not add it to the end of the file." but I'm not sure where to find ~/.profile

seancorfield21:07:03

classpath is not related to shell path (which is what ~/.profile and PATH is about).

seancorfield21:07:00

~ means "home directory". If you're in Terminal, ~/.profile will refer to your .profile file if it exists.

seancorfield21:07:48

Alternatively /Users/<yourusername>/.profile if you're after the full path (at least on the version of macOS I'm using).

Edward Ciafardini21:07:50

Ok - I see my Home directory when I open terminal. the "~" refers to this directory?

Edward Ciafardini21:07:28

If I use lein, is the classpath set somewhere automatically?

Edward Ciafardini21:07:42

Thank you for that info - I see "~" all the time, and never knew what it meant

seancorfield21:07:31

You can type

echo $PATH
to see what is on your path by default.

seancorfield21:07:05

Which instructions are you trying to follow?

Edward Ciafardini21:07:54

I was just using it to figure out what a classpath was

seancorfield21:07:47

Hmm, I just installed brew per the HomeBrew home page https://brew.sh/ and then brew install clojure/tools/[email protected]

seancorfield21:07:17

I don't remember needing to mess with .profile for that -- but my .profile has a lot of additional weird stuff in already...

seancorfield21:07:04

And this advice is definitely wrong: "Donwload and unzip Clojure" -- that tutorial is a bad one to follow. It's very outdated.

seancorfield21:07:34

https://clojure.org/guides/getting_started is the best place to start. Lots of tutorials out there are very out of date.

Edward Ciafardini01:07:08

Thanks! You're always so helpful

popeye11:07:34

when can we use dorun and doall ? i was going through documentation and I did not get actual use

delaguardo11:07:35

for example map function produces lazy sequence.

(def x (map #(prn %) (range 10)))
;; => #'user/x
;; no prints
(def x (doall (map #(prn %) (range 10))))
;; 0
;; 1
;; ...
;; #'user/x
so using doall will force map to perform all sideeffects

delaguardo11:07:48

the difference between dorun and doall is in the result. former will return nil but later will return collection

popeye12:07:28

what if we have any custom function in map which is not producing side effect? then dorun will be useful?

Joshua Suskalo14:07:33

Without side effects, then dorun will be useless to you unless you want a space heater, as it discards the returned value. The purpose of dorun is to run through a side-effecting lazy sequence without consuming your memory.

Joshua Suskalo14:07:08

doall is also going to be useless with a non-side-effecting function unless you really want the computation to happen immediately to prevent latency when looking up later elements.

Joshua Suskalo14:07:31

doall is very useful when you want to do a for comprehension with side effects.

popeye14:07:34

That helped, Thanks

max minoS12:07:36

I'm using figwheel-main, clj tool, and reagent and I'm unsure of how to mount the app,

(defn mount []
  (d/render [home-page] (.getElementById js/document "root")))

(defn ^:after-load re-render []
  (mount))

(mount)
this works but I've seen people do it in other ways, a lot of the docs show how to mount using shadow-cljs instead of figwheel

Geoffrey Gaillard12:07:19

mount looks good to me. re-render will mount one more time after each code reload. You might also want its opposite:

(defn ^:before-load unmount [] 
  (reagent.dom/unmount-component-at-node (.getElementById js/document "root"))
)
So you get: • initial mount • unmount before code reload • re-mount after code reload

🙏 2
athomasoriginal13:07:40

Here is the boilerplate template I use for CLJS projects: https://github.com/athomasoriginal/create-reagent-app

🙏 2
athomasoriginal13:07:00

Maybe that can provide some guidance

max minoS13:07:46

is there a particular reason you use (defonce start-up (do (mount) true)) instead of just (mount)?

athomasoriginal14:07:50

I this scenario, not yet. It’s meant for writing reloadable code. You want to control your side effects and that’s what this does

athomasoriginal14:07:20

I add it so that whoever uses this templ has a place to put stuff that should not re-render

👍 2
practicalli-john23:07:53

Creating a project with the figwheel-main template provides a very similar approach https://github.com/bhauman/figwheel-main-template This is what I use to start my own projects. It sets up some nice build profiles too

🙏 3
max minoS12:07:18

I'm also not sure how to connect CIDER to this (`clj -M:dev` then cider-connect doesnt work, and cider-jack-in does not connect to the project)

Geoffrey Gaillard12:07:30

Cider has to inject some dependencies. This is what cider-jack-in is for. Open deps.edn in your emacs then invoke cider-jack-in , it should detect the deps.edn file and run the clj command for you.

max minoS12:07:56

I tried this, but for some reason it still connects to the user namespace, that is how I can know that it is connected right (by seeing that it is in the project's namespace)? but even then, if I try (.log js/console "test"), it will say that there is no such namespace js

Geoffrey Gaillard13:07:37

Ah! You are connecting to a clojure repl, not a clojurescript repl, hence the js ns is not defined. I don’t know how to connect to a cljs repl using deps and figwheel. I use shadow-cljs.

👍 2
max minoS13:07:26

Thanks, I've found the answer. I just had to do cider-jack-in-cljs and choose figwheel-main and it works perfectly, as per the figwheel docs on using CIDER.

👍 2
Mícheál Ó Catháin18:07:41

hi there!  I'm having the same problem connecting cider to a repl.  I'm following both  and , but it's not quite right!  I can get a repl started from within emacs/cider by running cider-jack-in-cljs, but I can't evaluate forms within the .cljs files which is my main goal.  Any advice?

Geoffrey Gaillard20:07:07

Try to evaluate (type 1). If it returns object[Number] you have a cljs REPL. If it returns java.lang.Long, it's a clojure REPL.

Geoffrey Gaillard21:07:43

If it works but you can't evaluate from the source buffer, look at how sesman works with cider. Especially sesman-link-with-buffer https://docs.cider.mx/cider/usage/managing_connections.html

Geoffrey Gaillard21:07:10

Also remember that a cljs REPL has to be connect to a JavaScript runtime (browser or node)

Mícheál Ó Catháin13:07:52

@U2DART3HA many thanks! My repl does open correctly and links to the browser, with (type 1) returning #object[Number]; also entering (println "test") is reflected in the browser console.log.

👍 2
Mícheál Ó Catháin13:07:03

This narrowed the problem down to evaluating forms from the buffer holding my .cljs files. This wasn't working. I checked the sesman pages and it helped my understanding, however my brief checks didn't reveal anything obvious.

Mícheál Ó Catháin13:07:04

Next I noticed a warning was showing when I opened .cljs files -- "[warning] something in your configuration activated 'clojure-mode' instead of 'clojurescript-mode' for this buffer. This could cause problems." My emacs configuration is unchanged from the excellent Daniel Higginbotham's https://github.com/flyingmachine/emacs-for-clojure/. I browsed through the config files in my .emacs.d dir (I'm a very basic emacs user so this is a stretch for me!!) and couldn't see any obvious culprits although I imagine there needs to be a clojurescript specific addition.

Mícheál Ó Catháin13:07:40

Embarressingly, all I needed to do in the end was enter m-x clojurescript-mode. I can now evaluate (type 1) in the .cljs file buffer. This works, so even though not "perfect" it will keep me right for now. I'm sure I'll make the minor amendments needed to my emacs config when I become more familiar with emacs. Thanks for your help!

Geoffrey Gaillard13:07:45

Cider has three modes: - clojure-mode (clj) - clojurescript-mode (cljs) - clojurec-mode (cljc) The default configuration should map each file extension to the corresponding mode. If it doesn’t then probably something is overriding it. If your editor misaligns file extensions and repl types, you might also want to look at cider-set-repl-type. I havent found it in cider doc, but M-x describe-function RET cider-set-repl-type says

Set REPL TYPE to clj or cljs.
Assume that the current buffer is a REPL.
So if you have a cljs repl but your editor thinks it’s a clj repl: cider-set-repl-type RET cljs RET

Mícheál Ó Catháin14:07:12

Thanks @U2DART3HA really helpful to know about cider-set-repl-type. Yes, I think I will need to get my default configuration properly set up for clojurescript as well as clojure files. I imagine it could get very complex very fast if I keep using a manual approach, ie entering clojurescript-mode for each and every .cljs file I have open.

Geoffrey Gaillard12:07:30

Cider has to inject some dependencies. This is what cider-jack-in is for. Open deps.edn in your emacs then invoke cider-jack-in , it should detect the deps.edn file and run the clj command for you.

roelof16:07:45

I wonder if there is a study group for clojure and/or for learning to use react with clojure ?

Rob Haisfield16:07:02

Does anyone know why this isn’t working?

(def note-processing-sheet (spreadsheet/load-workbook "note-processing-sheet.xlsx"))
Execution error (NoClassDefFoundError) at org.apache.poi.openxml4j.util.ZipArchiveThresholdInputStream/<init> (ZipArchiveThresholdInputStream.java:63).org/apache/commons/compress/utils/InputStreamStatistics

Rob Haisfield16:07:53

I’m using Docjure

Rob Haisfield16:07:57

(ns functions-for-processing-notes.core
  (:require [dk.ative.docjure.spreadsheet :as spreadsheet]
            [com.rpl.specter :refer :all]
            [clojure.data :refer :all]
            [ :as io]
            [me.raynes.fs :as fs]))

Rob Haisfield16:07:32

I’m really confused because the code was literally working a few days ago and it’s unchanged

noisesmith16:07:48

have you changed your deps since then? you could compare the output of lein cp before and after the breaking change, I'd suspect some transitive dep issue or accidentally removed dependency

Rob Haisfield16:07:28

Huh, thanks for the heads up. I removed me.raynes.fs dependency and it started working again… any idea why that would be a problem?

noisesmith16:07:13

because transitive deps are tricky, it could be that the fs dep is old and pulls in a version ofcommons/compress that doesn't have the right class present

noisesmith16:07:45

in general anything from me.raynes is likely old and undermaintained (he was a productive member of the community RIP)

noisesmith16:07:48

it's likely there's a way to use fs, but use :exclusions or an explicit dep on commons/compress to make the right version come in

dpsutton16:07:03

there is a community maintained version i believe. i i think they maintain the same namespaces even though the coordinates have changed

dpsutton16:07:50

has src/me/raynes so that might be more recent than you think

Rob Haisfield17:07:40

Awesome, that makes sense, thank you

Rob Haisfield17:07:05

I’ll play with the current community version

Mitul Shah20:07:56

Would anyone have tips on setting up cache-control for static assets? also, using Reagent if that matters https://web.dev/uses-long-cache-ttl

phronmophobic20:07:43

cache-control is part of the server response and reagent is a client side library. How are you serving your website?

Mitul Shah21:07:04

We’re using firebase, I guess the config is in there, Thank you

phronmophobic21:07:09

A lot of website hosting options already have a recommended way to serve static assets that should (hopefully) use best practices