This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-10-30
Channels
- # announcements (15)
- # beginners (143)
- # boot (2)
- # calva (48)
- # cider (93)
- # cljsrn (2)
- # clojure (127)
- # clojure-europe (3)
- # clojure-italy (8)
- # clojure-losangeles (8)
- # clojure-nl (10)
- # clojure-spec (67)
- # clojure-uk (51)
- # clojurescript (20)
- # cursive (9)
- # data-science (2)
- # datomic (10)
- # duct (13)
- # figwheel-main (1)
- # fulcro (74)
- # instaparse (10)
- # jobs (3)
- # joker (8)
- # juxt (4)
- # lumo (1)
- # malli (11)
- # nrepl (3)
- # off-topic (4)
- # pathom (5)
- # pedestal (6)
- # planck (5)
- # re-frame (18)
- # reagent (5)
- # reitit (17)
- # shadow-cljs (165)
- # sql (30)
- # vim (12)
- # xtdb (6)
Hey friends, I have an uberjar running. I want to open a repl to it. Is that possible?
@nbtheduke Not from the outside. You need to either a) start the uberjar with JVM opts to tell Clojure to start a Socket REPL or b) program something into the app to explicitly start up some sort of REPL.
Good to know, thank you
If you don't mind restarting the app, you can just provide the JVM option to start a Socket REPL. We run local Socket REPLs in a lot of our processes and then tunnel into the server to get access to that.
Maybe I’ll try that next time I restart the app!
@seancorfield do yall take any steps to ensure that your socket repl access is "read only" in the sense that you don't redefine anything important?
We use those Socket REPLs to apply live patches to the running processes sometimes 🙂
I thought I remembered reading a blog of yours that you used to do that but had turned against it lately
Someone has to be able to ssh into the server to get at the REPL...
...We stopped running nREPL servers in processes. We didn't want the dependencies added.
(We used to run nREPL servers with full CIDER middleware enabled... and that was... a bit much... but a Socket REPL is built right in to Clojure so no deps needed for that)
We have an optional per-process dot file that the service script picks up so we can decide which processes get a REPL and what port it is on (and any other JVM option level stuff we want, when we want it).
How do you set this up? Do you have a blog post detailing?
Socket REPL? https://clojure.org/reference/repl_and_main#_launching_a_socket_server
I just don't get the enthusiasm for nREPL...
...I switched from Atom/ProtoREPL (which required a server-side dependency that included nREPL / Compliment etc) to Atom/Chlorine about a year ago, and I've really enjoyed not needing any server-side dependencies, and only minimal code loaded via unrepl (and I sort of wish Chlorine didn't even use that).
I thought it was a good day when Chlorine made Compliment optional recently -- and built its own simple auto-complete (that works just fine for me).
I suspect if I was still using Emacs, I'd be a big fan of inferior mode or whatever the simplest possible package that can connect to Socket REPL 🙂
I don't know what features are provided by nRepl. But what I do need is auto-complete, go to definition, debugging, pretty print, interrupt, run test, etc.
What "debugging" do you rely on?
I have no idea what that does.
It instruments a form or function, and then it can break, continue, in, out, inspect, trace, etc as you see fit
Hmm, I've never cared for that sort of thing much, in any language TBH.
I guess I've never felt the need. I like having tap>
available built-in (and I use REBL alongside Atom) but really I'm more in Stu's camp of simple tools...
I've had to use breakpoint debugging a few times during my years of Java (and years of C++ before) but that was because the language/tooling was otherwise just so awful.
I really liked Stu's debugging example where he redefined the exception handler to just print "boom!" and provide no info at all 🙂
It's not that you need it. And there's a lot I'm not a fan of with cider defaults. But that debug feature honestly is awesome. I feel it's a little unknown secret though
It just means instesd.of taking 5 to 10 minutes to add prints and defs and try/catches manually and all, it now takes me 1min to debug the same
I actually have inf-clojure and unrepl as well that I use in my emacs, because I don't think the issue is necessarily simple in the sense of featureless. But what cider lacks is simplicity in setup and usage
I think part of my fundamental objection to that level of intrusive debugging -- breakpoints -- is that you can't use it on a production app while it is running, whereas you can use the tap>
(or println
) approach...
Hum... well you could use cider-debug in prod, but you probably shouldn't, since it'll pause your thread
huh, til tap. seems nice. seems like it would mesh very well with something like http://honeycomb.io
For prod I wouldnt say I need all these things. Mostly goto, auto-complete, and doc would be nice for a prod repl. I like to use rebel-readlines in prod actually. I just ssh and start a rebel-readline repl
See, I like to be able to use the exact same tools and approach no matter where the app is that I'm working on / debugging.
That way I won't accidentally use the "wrong" tool in the wrong environment 🙂
In my case, I'm not allowed to open remote ports anyways to prod, and I can't ssh tunnel either 😔
I remember you talking about your work environment a bit... it sounded pretty corporate and locked-down... I'm surprised somewhere like that even uses Clojure 🙂
Hah... Neal Ford's sneaking Clojure in through the back door stuff...
(it was Neal Ford, right?)
Well, hey, all it takes for a Java app is adding Clojure as a dependency, add a JVM option, and -- bingo! -- you have a live REPL into your legacy/enterprise Java app 🙂
(after all, that's how come we have a REPL into our legacy ColdFusion apps! 🙂 )
Sounds cool, which JVM option do you add?
Pretty sure Sean means this https://clojure.org/reference/repl_and_main#_launching_a_socket_server
Btw. this might be useful when connecting to a socket repl running on a machine inside a private network available only via "bastion" host (e.g. on AWS):
# run in separate window
ssh -N -L 55550:localhost:5555 -J [email protected] [email protected]
# then use unravel to connect
unravel localhost 55550
Hi everyone! Would someone with experience on working with pedestal.vase and datomic-pro be available for the assistance I require?
I am trying to use vase standalone with datomic-pro. The thing is I can't seem to find the latest uberjar online at the link of the doc, and anyway it would be built for datomic-free. I tried to git clone the current github repo but it doesn't "lein uberjar" well even as is. I went back to the 0.9.2 release, commented out the datomic-free dep and added the datomic-pro (with the version I have a licence key to). lein uberjar suggested I excluded com.google.guava/guava, and then the uberjar was completed. But now I am thinking I can't use a .fern config, and I am wondering whether I am missing a way simpler option for all this...
^ You might wanna ask in #datomic
Thanks man yeah haha that makes a lot of sense. I am new to clojurians slack, didn't even explore the channels available apart from the automatic ones
Hi, I have question: Any mature open source system to learn about writing a system in clojure? (I posted on reddit, but think may get additional answers here) https://www.reddit.com/r/Clojure/comments/dp1p2t/any_mature_open_source_system_to_learn_about/
Watching the talk "The Language of System" () inspired me to learn practical clojure programming, by studying the source code of some open source systems written in clojure.
My criteria for such systems are:
* Not a library, not a framework, not a command line tool - but a full-fledged system or application. This is because designing/implementing a system has many unique considerations, e.g. a command line tool can simply abort on error, but a real-world system has to bear with it.
* stands to the tests of real world usage (no research/toy projects even if it has lots stars on github)
For other languages it's easy to find lots of candidates:
* python: zulip, openstack, ansible, etc.
* go: tons of CNCF projects (docker, kubernetes, etc)
* java: tons of apache projects (hadoop, hbase, zookeeper etc.)
* c/c++: countless of open source applications (xwindow, chromium, etc.)
However for clojure it's hard to collect candidate projects, maybe due to me short history with clojure itself, here are a few:
* apache storm (another project from the same author )
* metabase ()
Do you have any suggestions?
@UNMKEJQ1E I've just replied to the post. Thanks for raising this question
Thanks @U06BE1L6T!
Seems circleci's frontend is a good candidate for learning large-scale real-world cljs applications, but it's not updated for two years, anyone knew what happended to it? https://github.com/circleci/frontend
In a recent REPL podcast they mentioned they are moving to JavaScript/React: https://www.therepl.net/episodes/29/ For various reasons, I think mostly community/tooling (React/JavaScript just has a lot more support) and hiring
Thanks for the info @U06BE1L6T!
sorry, i was only engaged with circleci for a short time and don’t have much insight in to what happened after i gave that talk. you could try reaching out to some of the (much bigger than me!) contributors, or on twitter
so when I use swap! to assoc some items into an atom that is a map, the contents of the atom are printed in the repl and also when i run it through lein run
Something to keep in mind is the function passed to swap! may be called multiple times, so any side effects (like output) you don't want happening repeatedly shouldn't be in that function
I ran the -main function using lein run and it still prints the same thing to the std out
For any Clojure expression that has a result returned that you do not want printed in a REPL, you can do something like (def tmp <expression>)
where tmp
is some var you don't care about
What does your code in -main
look like?
Your -main
function is implementing your own custom REPL, it appears?
@andy.fingerhut your solution certainly will works but is there is a better solution?
Are you saying you don't want it to do the (println (pr-str res))
part, and removing that code makes it do what you want? I'm confused what printing output you are seeing that you want, vs. what you do not want.
I like (nil? expr) because it’s very short and tells me something that’s sometimes useful
@andy.fingerhut and @hiredman thanks for the help, I think I'm good for now with the suggestions
I might be misinterpreting but
user=> (= nil)
true
it can't provide information because it returns true for all arguments
You can always define a tiny macro whose name is a single letter long that expands to whatever you want, if you are trying to save characters of typing, e.g. expanding to (do expr nil)
or (let [res expr] (nil? ret))
Is there anyway to use define the keys in a spec outside of the spec and then evaluate the value inside the spec? Ex:
(def possible-keys [:all :the :keys])
(s/def ::special-map (s/keys :opt-un possible-keys))
That obviously doesn't work because macros, but I was wondering if there was a (preferably idiomatic way to get around that).
not easily no. you could write a macro to do it. also there is merge
for merging map specs together if that’s what you’re looking for
Not really. I'm defining a spec for a config map. The config comes from several parts is the environment map, and I need to filter that map to have only keys valid for the spec, so I need access to what keys are defined in the spec
I'd hope to have a vector storing the valid keys, which I would then pull from for both the filter and the spec
Ok, that would work. Just wanted to make sure that there wasn't a better way. Thanks!
The other way I forgot if it works with macros, but its worth a try. I believe if you declare the Var which holds the vector as constant
I don't know what you're talking about with s/describe, and #= is not a publicly supported feature so I would definitely not recommend that
well getting the keys is the easy part (should really use s/form though)
making the new spec is the hard part
If I understood the issue properly, I think they can make the spec, and just grab the keys from it to filter out the proper values from the config. So there's not actually a need for dynamic spec creation in this case.
you can do it by using either a macro or eval
user=> (def possible-keys [::all ::the ::keys])
#'user/possible-keys
user=> (eval `(s/def ::special-map (s/keys :opt-un [~@possible-keys])))
:user/special-map
user=> (s/form ::special-map)
(clojure.spec.alpha/keys :opt-un [:user/all :user/the :user/keys])
(note that even with :opt-un, you need qualified keys)
in spec 2, there are several ways to do this and you can use it without any macros at all if needed
in spec 2, one option is to resolve a symbolic spec and use register (no macros here):
user=> (require '[clojure.spec-alpha2 :as s])
nil
user=> (def possible-keys [::all ::the ::keys])
#'user/possible-keys
user=> (s/register ::special-map (s/resolve-spec `(s/keys :opt-un [~@possible-keys])))
:user/special-map
user=> (s/form ::special-map)
(clojure.spec-alpha2/keys :opt-un [:user/all :user/the :user/keys])