This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-01-09
Channels
- # announcements (9)
- # beginners (69)
- # cider (4)
- # clj-kondo (8)
- # cljdoc (1)
- # clojure (52)
- # clojure-austin (4)
- # clojure-europe (22)
- # clojure-nl (2)
- # clojure-norway (14)
- # clojure-uk (3)
- # clojurescript (9)
- # conjure (4)
- # cursive (3)
- # datalevin (13)
- # datomic (4)
- # events (2)
- # fulcro (59)
- # graalvm (17)
- # helix (25)
- # inf-clojure (4)
- # integrant (4)
- # introduce-yourself (2)
- # java (5)
- # kaocha (1)
- # leiningen (3)
- # meander (7)
- # nbb (4)
- # off-topic (30)
- # portal (4)
- # rdf (1)
- # reagent (5)
- # sci (1)
- # shadow-cljs (57)
- # sql (8)
- # tools-deps (39)
- # uncomplicate (3)
- # vim (3)
- # xtdb (8)
Hi. I’m new to clojure. Started with Kit framework. I’m unable to connect to clojurescript shadow-cljs repl. Anyone has experience with this?
Idk what your setup is like but I've had success starting a cljs repl in the terminal and then connecting to that in my editor
https://shadow-cljs.github.io/docs/UsersGuide.html#_repl the shadow users guide is helpful in my experience as well
from kit docs, i could see npx shadow-cljs watch app starts the repl in port 7002. But what i’m seeing is this which is running on different port
This port is different and when I try connecting to this port from emacs, I get “sync nEPL request timed out” error
I'm no expert in the matter but I do believe port 9630 is where the websockets for the app watch are running
Thank you. I could already see some improvements from the links you have shared.
The last time I did CLJS I think i just used npx shadow-cljs clj-repl
in my terminal
I think there's a corresponding command for a cljs repl as well
I just changed the ports. Its working now. Thank you!. Seems my machine is somehow interferring with the default ports given in kit framework
The 9630 port shown in your screenshot is not your app. That is the Shadow CLJS service. Opening that that port in your browser shows a Dashboard (which includes a link to the local address of your app when it's running).
You typed Ctrl-C
at the bottom of the screenshot, before either an NRepl server or an HTTP server had a chance to start.
What is the state of Clojure editors (perhaps IDEs) in 2023? I was happy with Atom, now using VSCodium but want to leave it. Both because I’m not clicking with it, but maybe more for ideological reasons. I’m after something really simple. If I could have syntax highlighting and basic REPL integration I’d be happy. Don’t need refactorings or… almost anything. My specific situation is such that I spend the odd hour here or there doing Clojure and so ease of use and getting up and running quickly is helpful.
almost every modern IDE have clojure packages with mostly the same set of features. I would recommend stick with IDE you know the most
Doom Emacs without the evil-mode junk (just comment it out in init.el, uncomment (clojure +lsp), install clojure-lsp) and you should have a relatively smooth experience with clojure-mode, Cider & LSP
I’m partial to emacs (and have opinions on the “easy” part), have used it in the past (somehow at the same time I discovered muds…). I’m most often on a Mac, any special considerations with emacs?
I would just recommend reading the detailed install guide for mac on the doom emacs github page. If it looks too daunting or tedious, then pass
https://github.com/doomemacs/doomemacs/blob/master/docs/getting_started.org#on-macos
I haven't used emacs in many years, so can't compare, but I found Sublime Text 4 to be a very pleasant experience, with clojure-lsp providing autocomplete and linting (clj-kondo), and https://github.com/tonsky/Clojure-Sublimed providing syntax-highlighting and nREPL-connection.
For the criteria specified in the original post, then all the common editors would suffice. I suggest SublimeText and ClojureSublimed is the simplest in terms of install / configuration
If opting for Emacs, I found https://github.com/d12frosted/homebrew-emacs-plus the most useful approach to install on the MacOSX Using a config for Spacemacs or Doom can simply the installation, assuming the features are congruent with your workflow https://practical.li/spacemacs/ https://practical.li/doom-emacs/
One more vote for emacs from me - but I go with the approach of installing vanilla emacs then picking and installing only the packages that I need. The benefits to me (1) I find it's a smaller learning curve compared to a full kitchen sink copy of emacs like Spacemacs (that has loads of preinstalled packages/special key bindings/modes etc). (2) Most generic emacs help on the web (e.g. the kind found on stackoverflow) is more likely to be useful.
Hello clojurians. I'm using ClojureScript, shadow-cljs with a node.js repl to interface some npm libraries which return complex objects that I need to inspect.
For example #object[t [object Object]]
.
I can (js/console.log x)
it, but it only resolves the first layer in, and I want to explode and inspect the object further.
Preferably, I would want to inspect this object in the browser. But I need to use node.js for access to my filesystem.
What would be the preferable way to go about this?
I thought about sending the object to a dev browser, but it seems like overhead.
This question was posed after a long programming session became frustrating 🙂
The answer is to prepare the data and use js->clj
What in your experience is the best way to handle nil in a threading macro?
I'm thinking of something like this
(-> id
(query-user-db)
(if-nil?
(respond-error "user not found")
(respond-mapped-user))) ; receives user as parameter
But maybe there is a smarter pattern, that I don't know.
To my eye the threading is not doing any help here. You want a simple conditional on (query-user-db id)
. I’d use if-let
of if
in this case
I shortened the threading a bit for this example.
I am doing
(-> (:id request)
(->UserId)
(query-user-db)
(if-nil?
(respond-error "user not found")
(respond-mapped-user)))
I like the readability of that, but maybe I should just pass the result to a conditional.
(if-let [user (-> (:id request)
(->UserId)
(query-user-db))]
(respond-mapped-user user)
(respond-error "user not found"))
(or (some-> (:id request)
(->UserId)
(query-user-db)
(respond-mapped-user))
(respond-error "user not found"))
but i don’t like this style as muchthank you very much.
The if-let
version reads nicely.
Since some->
can only solve this in combination with the or
I don't like it as much as the if-let
.
The behavior of if-nil?
, to call an else-branch with its non-nil input, is definitely not intuitive or obvious.
Your original code looks just fine to eyes, if you just replace that weird function with a normal if
construction.
(-> (:id request)
(->UserId)
(query-user-db)
#(if %
(respond-mapped-user %)
(respond-error "user not found")))
And if you did need to explicitly check for nil
(in contrast to a possible false
), that would simply mean changing if %
to if-not (nil? %)
, which still keeps the user-exists case in the passing branch where it intuitively belongs.If you have long bits of error prone code, failjure is pretty cool for monadic error handling: https://github.com/adambard/failjure#ok--and-ok-
@U90R0EPHA that is a very good point you are making there. That is simpler, nicer to read and easier to unterstand. But it does throw a compiling error.
Yep. That makes sense; since I forgot to giftwrap the anonymous function 🎁.
(-> ...
(#(if %
...)))
I am trying to resolve an old issue where I can't run some code inside a jar file, @alexmiller mentioned that I may need to define the ServiceImpl in the jar manifest, not coming from java I missing terminology, I am not sure what an impl is or where I can find out what I need to add to the manifest file. The service in question is bing ads, I have been running it from the clojure cli instead of the built jar but hoping someone can point me at anything that will help me fill in the blanks in my knowledge.
What is the question? 🙂
well I guess if I need to add a service impl to the manifest, under what setting and how would I find out what the correct value would be 🙂
Do you have a repro or a link to the original issue?
com.microsoft.bingads/microsoft.bingads {:mvn/version "13.0.13"}
This being the offending library that will not work in an uberjarso basically if I run with clj -M:run it works but as soon as I build an uberjar it fails
unfortunately its not a public repo its an internal company project, this is the error I get when running from an uberjar
Exception: #error {
:cause Cannot invoke "org.apache.cxf.jaxws.spi.WrapperClassCreator.generate(org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean, org.apache.cxf.service.model.InterfaceInfo, boolean)" because "wrapperGen" is null
:via
[{:type java.lang.NullPointerException
:message Cannot invoke "org.apache.cxf.jaxws.spi.WrapperClassCreator.generate(org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean, org.apache.cxf.service.model.InterfaceInfo, boolean)" because "wrapperGen" is null
:at [org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean generatedWrapperBeanClass JaxWsServiceFactoryBean.java 670]}]
One of those problems I looked into ages ago never got very far so had to use a work around, hoping I can bring the job in line with all my other jobs
I don't know what's the root cause for this but the offending line in the actual source code of the library is this: https://github.com/apache/cxf/blob/8dbb29c3ff09f320c90da5af1e74bb79e66b1328/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsServiceFactoryBean.java#L670
it tries to call the generate
method of org.apache.cxf.jaxws.spi.WrapperClassCreator
for a null object, therefore you get that exception.
This shouldn't return null but it does when you run the code from the jar: getBus().getExtension(WrapperClassCreator.class);
I don't know what that means though (any idea what getBus()
does?)
no idea, looking at https://cxf.apache.org/ makes me think it may read some kind of definition file that's not in the jar perhaps
Ohh, getBus
is a method of AbstractServiceFactoryBean
which WrapperClassCreator
extends, that's why it can access it directly (haven't touched Java in ages, totally forgot about inheritance 😐)
well this is where I struggle with clojure, never touched java so when it comes to interop and terminology It can be a struggle.
Unfortunately this particular case is 100% Java, so as the saying goes, you ask for a banana but you also get the gorilla and the whole forest.
I'm not sure why Clojure the JVM gives that stacktrace though. If a class definition was missing I'd expect a different kind of error. (something like class not found or something)
> Ohh, getBus
is a method of AbstractServiceFactoryBean
which WrapperClassCreator
extends, that's why it can access it directly
this sounds like satire 😂 @UEQPKG7HQ
Does it use the ServiceLoader to get the service impl?
If so, you need to provide an implementation via
a configuration file in META-INF/services
The file in the services folder has to have the fully qualified name of the Service interface it implements.
The content of the file is the fully qualified name of the Class that implements the service.
For example
The file in Meta inf is:
META-INF/services/com.superb.java.Service
The content of the file is
my.superb.ServiceImpl
ServiceImpl obviously implement Service.
This works for clojure implementation with :genclass
.
Hope that is somewhere near you problem 🙂
@U04HGPMQJJG this sounds like it could be a possibility I will dig and see what I can find out, but this is the sort of thing I got the impression I may need to do.
is there any info on how you modify the content of MET-INF should i just create the files, or perhaps do I pass in some param to tools build config ?
The write-pom task takes a map of props to set in the manifest (and you should use that vs making it yourself as the format is weird)
I’m talking about the manifest file itself
If you need other files, then yes you would need to either copy or make those yourself
okay thanks for that info @alexmiller does tools build give a way todo this or do you just create META-INF/services/file in your project and it gets included when the jar is built ?
tools.build expects you to copy/create files that should end up in the jar in your classes directory, so the build process can either copy from somewhere (using copy-file or copy-dir tasks) or even spit it directly from the build process if that makes sense