Fork me on GitHub
#clojurescript
<
2022-02-23
>
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.

p-himik12:02:34

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"}}

ichramm12:02:44

you can just use merge:

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

p-himik13:02:31

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.

p-himik13:02:57

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

p-himik09:02:51

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?

p-himik10:02:21

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 https://www.braveclojure.com/functional-programming/ or https://www.learn-clojurescript.com/section-4/lesson-21-functional-programming-concepts/ and any other materials you can find on the topic when applied to Clojure.

p-himik10:02:01

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

kokonut13:02:05

hi, i have a newbie question. i am trying to use halfmoon in my cljs project, which is based on shadow-cljs. https://www.gethalfmoon.com/docs/download/ 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:
require("halfmoon/css/halfmoon-variables.min.css");
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!

p-himik13:02:51

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.

p-himik13:02:15

Also, there's #shadow-cljs

kokonut13:02:29

yep, i see.

kokonut13:02:32

thanks.

đź‘Ť 1
martinklepsch14:02:19

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

lilactown15:02:00

are you trying to do a "dynamic" require?

martinklepsch16:02:17

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

martinklepsch16:02:59

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

martinklepsch16:02:35

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)
    `~enabled
    `~disabled))

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...

p-himik15:02:40

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

p-himik15:02:56

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)

p-himik15:02:46

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

p-himik15:02:41

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

p-himik15:02:55

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

p-himik15:02:17

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: https://cljs.github.io/api/cljs.core/goog-define

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?

p-himik16:02:07

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 see...do 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:

p-himik16:02:13

Do you use shadow-cljs by any chance?

Dimitrios Piliouras16:02:32

I got it to work using env-variables

đź‘Ť 2