Fork me on GitHub
Rambabu Patina12:02:41

Hi, How do I check whether the CLJS data structure has key? otherwise add it I want's to check the key 'ghi' in below

 'abc': 'first',
 'def': {
     'j': 'sub'
If not exist add it as below
 'abc': 'first',
 'def': {
     'j': 'sub'
 'ghi': {
     'k': 'test'
Please help.


You example looks like a JS object and not a CLJS map. Is that correct?

Rambabu Patina12:02:44

Yes. Here is the CLJS structure

{:abc "first" :def {:j "sub"}}

Rambabu Patina12:02:29

And want's to add like below if 'ghi' does not exist

{:abc "first" :def {:j "sub"} :ghi {:k "test"}}


you can just use merge:

(merge {:ghi {:k 'test}} 
       {:abc "first" :def {:j "sub"}})


The merge approach is reasonable only when the second map is small and its real type doesn't matter. In any other situation, you should use contains? with assoc.


Or a single update if you consider nil values to be the same as absent keys.

Rambabu Patina08:02:41

Does assoc/update returns new map? If yes I wants to update the existing map


Clojure[Script] data structures are immutable. You're supposed to return a new map and use it instead of the old one. If at a single, very specific place, you can't practically use that paradigm, you can store your map in an atom and swap! it with the function you want.

Rambabu Patina09:02:41

Thanks for answering! Can we assign back the returned map to same map?


No, but you use the atom everywhere instead of directly using the map. Since it seems like functional programming is a new thing for you, I encourage you to read or and any other materials you can find on the topic when applied to Clojure.


Also note that there's #beginners, which is the most appropriate channel for any kind of entry-level questions.


hi, i have a newbie question. i am trying to use halfmoon in my cljs project, which is based on shadow-cljs. and install it using npm (yarn in fact) like the following as the document suggests:

npm install halfmoon
the above doc says that once installed it can be loaded by the following two lines:
const halfmoon = require("halfmoon");
i think the second line can be expressed in cljs (please let me know if wrong)
(:require ["halfmoon" :as h] ...)
but i am not sure what i should do about the first line requireing the css file in cljs. Or maybe should i copy/paste the line in index.html file? can someone enlighten me here? thanks!


The simplest way is to just refer to the CSS file directly in your index.html, maybe copying the file some place out of node_modules - depending on how you deploy your project.


Also, there's #shadow-cljs


yep, i see.



đź‘Ť 1

Can a macro modify the ns form of the namespace it’s called in?


are you trying to do a "dynamic" require?


yes, basically. I’m trying to figure out how to balance stuff like lazy loading and SSR


shadow’s reader conditionals make it possible in a way but I don’t really like reader conditionals in a mostly cljs code base, just seems like a lot of cruft and a bit of an “invasive implementation” detail that will hurt readability & comprehension


Wondering of shadow build hooks could help with it but seems like in general its gonna be a bit of a lift to make it work

Dimitrios Piliouras14:02:41

Hi all, I am struggling to write a (pretty basic) CLJS macro which uses compile-time constants (e.g. goog-define) in order to emit different code - for instance:

(defmacro with-feature
  [id enabled disabled]
  (if (contains? app.config/features id)

Dimitrios Piliouras14:02:11

where do I put that macro so that the compiler doesn't complain it can't resolve app.config/features ?

Dimitrios Piliouras14:02:00

I realise it has to go in a CLJ namespace, but it needs visibility of app.config/features which is in a CLJS namespace

Dimitrios Piliouras14:02:50

Is that even possible?

Dimitrios Piliouras15:02:11

many thanks in advance...


The CLJS namespace that uses that macro must have app.config in its requires.

Dimitrios Piliouras15:02:34

Thanks for your reply, but that doesn't seem enough. I'm requiring the namespace everywhere, but I still get: failed to require macro-ns "app.config", it was required by "app.config"

Dimitrios Piliouras15:02:00

Error in phase :compile-syntax-check

Dimitrios Piliouras15:02:28

FileNotFoundException: Could not locate app/features__init.class, app/features.clj or app/features.cljc on classpath.

Dimitrios Piliouras15:02:07

ah sorry that's the wrong error

Dimitrios Piliouras15:02:35

[1] failed to require macro-ns "app.config", it was required by "app.config"
[1] Error in phase :compile-syntax-check
[1] RuntimeException: No such var: app.config/features


I'd deal with the first line first - sounds like it could be the cause for the other errors.

Dimitrios Piliouras15:02:55

So I have a CLJS namespace with a declaration like the following:

(ns app.config
  (:require [clojure.string :as str]
            [app.util :as util])
  (:require-macros [app.config])) ;; <======

Dimitrios Piliouras15:02:47

Then I have a CLJ namespace with the same name containing only the macro shown earlier (no requires)

Dimitrios Piliouras15:02:18

It seems that the CLJS namespace cannot require the CLJ macro namespace because the macro contained in it references unresolved Vars (i.e. app.config/features)


Ah, wait, my bad - I read the macro incorrectly. In your code, you use app.config/features in macro expansion time. You have to quote the outer form, so move the syntax quotes outside of if.

Dimitrios Piliouras15:02:38

well yes I can do that and it works, BUT then I'm emitting the check for runtime

Dimitrios Piliouras15:02:52

i would like to do the check at compile time

Dimitrios Piliouras15:02:13

because everything i need to decide which code to emit is a compile-time constant


Right. Things defined with goog-define are compile-time constants indeed. But macro expansion is done before CLJS compilation. :)


So sounds like you'd have to either stop using macros or switch from goog-define to something else.


Note that DCE works just fine with goog-define if you have the right tags - so there might not be any need in macros.

Dimitrios Piliouras16:02:23

I don't just want to elide code...i'm trying to write a rudimentary feature-flagging system...I want to be able to say: when this feature is enabled emit this expression, otherwise emit this other expression.

Dimitrios Piliouras16:02:16

What I want is fairly similar to what is shown here:

Dimitrios Piliouras16:02:36

the difference is that instead of when I want to use my own macro

Dimitrios Piliouras16:02:50

so are you saying that a CLJ macro cannot use any CLJS vars at macro-expansion time even if these are compile-time constants?


Because macro expansion is an earlier step. Unless you define your goog constants in a way that can be introspected with CLJ code.

Dimitrios Piliouras16:02:10

I you happen to have the slightest idea how that might look?

Dimitrios Piliouras16:02:35

I will try that - many thanks for your time :thumbsup:


Do you use shadow-cljs by any chance?

Dimitrios Piliouras16:02:32

I got it to work using env-variables

đź‘Ť 2