Fork me on GitHub
Braden Shepherdson03:02:41

I'm having a lot of trouble writing CLJC-friendly macros. it feels like a piece of the story is missing. • I can emit different code for each platform with net.cgrand.macrovich/case • I can have CLJS-only code and deps with #?(:cljs ...) • but I can't have proper CLJ-only code or deps - it all runs at macro expansion time too. I keep finding myself wanting #?(:clj/jvm ... :clj/macros ...) or something like it. the only solution I can find is just adding all the JVM-side deps to my shadow-cljs build. am I missing a solution to this problem?


I wonder if this pain goes away a bit if we use deps.edn to manage the deps rather than separately in shadow-cljs. Sounds like the problem is writing macros for two very distinct class paths rather than :clj/jvm and :clj/macros

Braden Shepherdson03:02:05

something about that approach bugs me, but it's probably the most practical anyway. duplicating the version numbers between deps.edn and shadow-cljs.edn is going to be a pain eventually.


i think tooling with CIDER gets a bit more annoying when the process isn’t managed by shadow-cljs. Hazy memory but starting the server and adding the shadow nrepl middleware are manual.


but maybe it has improved since i’ve looked


I’ve had luck using shadow-cljs in leiningen with CIDER. All I had to do was add one thing to my :nrepl-middleware


unfortunately its not possible to add custom :cljs/macros literals for CLJ files. you can use them for CLJS, but that doesn't help here


if it would help I could add a binding that is only set when loading macro namespaces, but not sure that makes things much cleaner

Otto Nascarella16:02:58

hi there today a coworker reported this here at Pitch: In CLJS (name (keyword "foo/bar/baz")) is "foo" In CLJ (name (keyword "foo/bar/baz")) is "bar/baz" Should it not be the same?

🙂 2

I would wager cljs doesn't support namespaced keys but I'm far from an expert EDIT: I am wrong

Alex Miller (Clojure team)16:02:04

these are not valid in either language and thus this is undefined


The first argument to keyword is name. And it cannot contain slashes by definition of what a keyword is.

Alex Miller (Clojure team)16:02:43

from on symbols (keywords are "like symbols"): > '/' has special meaning, it can be used once in the middle of a symbol to separate the namespace from the name, e.g. my-namespace/foo

Otto Nascarella16:02:42

I understand that only one “/” is allowed. I was just wondering if the output should not match either way

Alex Miller (Clojure team)16:02:33

you should not expect anything of an undefined syntax :)

✌️ 2

@U064X3EF3 Would you say that (keyword "a/b") is valid, even though it tries to create a keyword with a name "a/b"?

Alex Miller (Clojure team)16:02:00

The keyword function intentionally does not validate its inputs and defines hows it works in the docstring. If you pass it invalid inputs, you will receive invalid output. It does not validate, because Clojure would be significantly slower if it did.


That's a general theme isn't it, @U064X3EF3 ?


@U064X3EF3 Yeah, I get that. The question is about whether it's intentional that "a/b" "works" - i.e. it seems to parse the string and creates a keyword with namespace a and name b. I'm wondering whether it's intended and correct behavior of (keyword "a/b") and it can be relied on or whether (keyword "a/b") should be avoided as the above is an example of correct but undefined behavior.

yes 2
Alex Miller (Clojure team)16:02:10

sorry if I misunderstood

Alex Miller (Clojure team)16:02:04

the docstring does not say it does that, so either you shouldn't rely on it, or the docstring is wrong


The implementation suggests that it's intentional, even the argument name is nsname:

static public Symbol intern(String nsname){
	int i = nsname.indexOf('/');
	if(i == -1 || nsname.equals("/"))
		return new Symbol(null, nsname);
		return new Symbol(nsname.substring(0, i), nsname.substring(i + 1));
But yeah, the docstring doesn't mention it. Maybe it should? Should I create an "ask" for it?


Hello! What is the best way to use react components from NPM in reagent+shadow-cljs project? I try to use "react datepicker" and do it quite straightfroward: (:require ["react-datepicker" :as dt :default ReactDatepicker]) The component appears, but there is no CSS. In JS i should use import "react-datepicker/dist/react-datepicker.css"; , but how to do the same in clojurescript + reagent?


You have to load the CSS manually. Also, the supported way for requiring the default export is to use (:require ["react-datepicker$default" :as ReactDatepicker]).


I usually add such CSS files to my main bundle with @use instructions that are later processed by SASS.


Thank you? Could you please help me with importing CSS? Where should I put something like 'import "react-datepicker/dist/react-datepicker.css";' ?


oh, I dont use SASS. Is it possible to do it without SASS?


You don't do it in the CLJS files, that's for sure, unless if you're using some tricky setup. Even in the JS world, when you use import "...css";, it's actually much further from being simple than you might think - WebPack or some other bundler is doing a lot of work in the background. If you don't use SASS, you can use shadow-cljs hooks to copy the right files to the resources folder of your project and then refer to those files from your index.html.


Thank you! With your hints I hope now I will be able to figure this out.

👍 2

Hello. I was wondering if there's a way to specify (deps.edn) aliases when running shadow-cljs via npx I tried npx shadow-cljs -A:my-alias watch dev-ui and also tried putting the -A to the end, but I doesn't seem to have the desired effect. Thanks in advance!


there is not, but you can just flip it and use clj directly, instead of npx. clj -A:my-alias -M -m shadow.cljs.devtools.cli watch dev-ui


note that all classpath trickery is usually not necessary and there are better options for doing things. so, why do you want a specific alias for this build?


I have browser and server(node.js) builds in the same shadow-cljs.edn file (nodejs server for API, browser build for UI). > In another project I have them separated (2 shadow-cljs.edn files, 2 different ports to bind to). As an intermediate step I tried to start separating the UI and server deps under their own aliases) Do you have recommendations on how to organize the code in such case? (where there's browser & node.js server build). Aliases / separate shadow-cljs projects / define each project as lib (with their own deps.edn) and include the file as "library"? / ...


just keep everything in one project?


I inherited this codebase in its current form (it was using leiningen and some other tools before. I'm looking for better ways and suggestions


the builds decide what is used. so having extra dependencies has no effect on the build, so the separation that was necessary in lein-cljsbuild is not needed

🎓 2

so, just one alias, two builds and you are good to go


Oh, I see. Thanks for the great tools too you've built! Makes working so much nicer 🙂

👍 2