Fork me on GitHub
#polylith
<
2021-08-16
>
allandaviesza14:08:56

When visiting a Clojure file in a base, I invoke cider-jack-in, this starts a REPL which reads the dep.edn file of the base, what I intended was to read the deps.edn file in the root of the workspace, has anyone had this problem and found a way around this? (I am aware that this is the correct behaviour, just wondering if anymore has a work around to always read the workspace deps.edn config)

pithyless14:08:17

I always do the initial connect to the REPL via the user or dev ns in the development project.

allandaviesza14:08:51

Yea I've been doing the same

Karol Wójcik15:08:39

@U05476190 how do you setup the nrepl?

pithyless17:08:57

I just run clojure -M:with:lots:of:dev:aliases and then cider-connect-clj. I never figured out how to use cider-jack-in and find it easier to configure the REPL classpath via CLI tools :)

seancorfield17:08:46

At work we always start the REPL from the terminal because our REPL outlives our editor sessions (we run REPLs for days or weeks -- or sometimes months) but our editors tend to get restarted a lot more often.

seancorfield17:08:42

My work REPL has been running since August 11th at this point (not very long) but my HoneySQL project REPL has been running since July 18th.

seancorfield17:08:30

(and my depstar project REPL has been running since July 9th)

seancorfield17:08:41

My work REPL is started like this:

(! 509)-> SOCKET_REPL_PORT=5000 clojure -Sforce -M:rebel:reflect:jedi-time:reveal:j14:classes:everything:dev:test:build:runner:dev/repl
That :dev/repl alias comes from my dot-clojure repo setup on GitHub and starts Rebel Readline, Reveal, and a Socket REPL, plus it adds some customizations to Reveal.

seancorfield17:08:47

:dev:test is the Polylith portion. :everything:runner is our legacy subproject stuff. :build is our build.clj stuff with tools.build. :reflect is Stu Halloway's reflector utility to improve datafy/nav for namespaces. :j14 enables some JVM options to improve error reporting (well "improve" is subjective). And :classes adds the classes folder where I have AOT'd code for some dev load improvements (per the http://clojure.org page about that -- but I don't really use it much). Normally, I'd also have :add-libs in there for adding dependencies on-the-fly (but recently it has conflicted with tools.build so I haven't bothered -- although Alex just merged master to the add-lib3 branch so I may pick that up again).

allandaviesza06:08:06

kool, thanks for the info, I guess starting the REPL from the command line is the way to go, or a clunky jack in if one must

jasonjckn18:08:20

@allandaviesza just ran into this, so I wrote a quick hack for it

jasonjckn18:08:26

(after! clojure
  ;; (setq clojure-cache-project-dir nil) ; you may need this

  (defun locate-submissive-file (file name)
    (let ((it (locate-dominating-file file name)))
      (while-let ((maybe-descend-to-parent (and it (locate-dominating-file (file-name-parent-directory it) name))))
        (setq it maybe-descend-to-parent))
      it))


  (setq clojure-project-root-function
        (defun my/clojure-project-root-path (&optional dir-name)
          (or (locate-submissive-file (or dir-name default-directory) "deps.edn")
              (clojure-project-root-path dir-name)))))

allandaviesza14:08:12

I'm using Emacs and CIDER

👍 3
emacs 3
Matt Ielusic22:08:39

What's a good way to have a def that a component both uses & exposes? The polylith tool readme suggests putting something like (def one-two-three 123) in the interface, but then the component's implementation can't access the value (because of the circular dependency implementation -> interface -> implementation). The obvious thing is to have an interface def that points to an implementation def, but then you can't with-redefs it for testing.

seancorfield22:08:15

The most common thing I've seen if (def one-two-three 123) in the implementation and then (def one-two-three impl/one-two-three) in the interface. with-redefs can be fairly problematic so I'd question how you get yourself into a situation that needs to redef a def (as opposed to a defn).

seancorfield22:08:14

If you have a global value, it's going to get compiled into the functions that use it so with-redefs on such a value isn't going to work anyway.

Matt Ielusic22:08:06

There's a test that was written for the non-Polylith repo that with-redefs the var

seancorfield22:08:35

That's a problem with the current test then I'd say - per above : Def values will be compiled into uses and can't generally be redefd

seancorfield22:08:02

(sorry for typos - power just went out and I'm on my phone now)

Matt Ielusic22:08:01

I'm not sure what you mean by "global value"? I just have a def for something that depends on how the program was started. And that needs to be tested with multiple values.

emccue22:08:42

can you be a bit more specific as to what the value is/represents/depends on

emccue22:08:26

in the worst case scenario you can just make an explicit test hook in the interface

emccue22:08:35

(def abc impl/abc)

(defmacro with-custom-abc* [new-abc & body]
  `(with-redefs [impl/abc new-abc]
     (do ~@body)))

emccue22:08:16

little * at the end to indicate "experts only, not a part of the interface"

Matt Ielusic22:08:44

My def is for a system property

emccue22:08:20

so its like (def abc (System/getProperty "xyz"))?

Matt Ielusic22:08:17

I don't think that macro quite works? It needs to redef both the core and interface var (as I have discovered the hard way.)

emccue22:08:34

(def abc impl/abc)

(defmacro with-custom-abc* [new-abc & body]
  `(with-redefs [abc new-abc
                 impl/abc new-abc]
     (do ~@body)))

emccue22:08:38

like this?

Matt Ielusic22:08:11

I think so. I almost want to put it in the core file, just to emphasize that it's not really for public use.

emccue22:08:47

you can also make the property derefable

emccue22:08:51

by which i mean

emccue22:08:16

(def abc (delay (System/getProperty "xyz")))

emccue22:08:32

which introduces some indirection, which would let you get away with only redeffing one

emccue22:08:33

so @abc or (abc)

emccue22:08:49

to be clear i'm still not really good/sold on polylith so maybe my advice is tainted

seancorfield23:08:12

Having a global def just reading off the environment when the ns is loaded is a very bad idea since it'll run when you AOT your code as well as when you require the ns -- that's essentially a side-effect (dependent on the state of the "world") so it should really be a function.

👍 6
seancorfield23:08:36

(at a bare minimum it should be behind a deref as Ethan suggests but even that is somewhat poor practice IMO)