Fork me on GitHub

Hey, in cljs I'm trying to iterate over a list of objects (ratom) to generate an error field with gen-field-error. I want to pass the field object name in a loop, so when I iterate over company-name I will pass "company-name" as a string.

(def company-name        (r/atom ""))
(def company-logo        (r/atom ""))

(def required-fields

(defn gen-field-error [field]
  (-> field
      (string/replace #"-" " ")
      (str " is required.")))
I tried with
(-> (first required-fields) (var) (meta) :name)
But unsuccessfully due to some problems with var


This wouldn't work in CLJ either. When you wrap a symbol in [], that symbol no longer exists within [] - only its value does. In order for #'... or (var ...) to work, they have to receive the symbol itself, at compile time. CLJ has run time capabilities for that where you can get a var from a namespace by its name as a string. But CLJS does not - you have to create your own dictionary of names to values and use that.

🙏 1

Okay good to know! At this point I will say or I use ns-interns and check the type of every value or I can transform required-fields in a big ratom and simply use keys on it


Note that in CLJS ns-interns is a macro that has to receive a symbol, so stuff like *ns* won't work there.

👍 1
Lukas Domagala18:11:17

is it possible to have an optional require in cljs? wrapping a require call in try-catch doesn’t work as it has to be at the top level


actually optional is for data that can be or not there, exception is for flow that will fail (eventually), they seems like different concepts to me…


I’m looking for a lightweight DB to drive from node/nbb, could be datalog but I’ll need persistence. Suggestions?


lots of node dbs. i'd start there


I found lowdb but that doesn’t seem very ergonomic, do you have any particular ones that you’ve tried/liked?


i've been out of the node.js world for awhile. prior i would probably just use something like sqlite or redis


i think there are a couple cljs dbs that persist to local storage or something. maybe you could use some duct tape and wire to get those to persist to some durable storage in node.js


but sqlite is hard to beat


I ended up using Google sheets lol


Kind of not what I would have expected as an answer to my question but in the context of what I’m working on I think it makes sense


@domagala.lukas you can probably use a macro and try finding the optional ns on the classpath in the macro


hmm, no, you cannot use a macro to generate an ns form in CLJS.


The way I usually do this is to let the consumer of the library pre-require the optional namespace

Lukas Domagala19:11:03

@U04V15CAJ what do you mean by pre-require?


e.g. for clojure spec alpha, the user has to require clojure.test.check first to use certain features.

Lukas Domagala19:11:14

@U04V15CAJ ah yeah, thats clever, since js doesn’t really care. the two problems are: shadow + clj-kondo really like warning me now, but i guess i’ll find a way to make them stop


can you give an example of what clj-kondo "complains" about?

Lukas Domagala19:11:24

(def debux-enabled?
       (when (exists? debux.common.util/result*)
       (catch :default _ false)))
that part only bothers clj-kondo. shadow only complains about:
(if debux-enabled? debux.common.util/result* [])


clj-kondo should support this:

$ clj-kondo --lint - --lang cljs <<< '(exists?'
<stdin>:1:10: warning: Unresolved namespace Are you missing a require?
Can you make an issue?


I'll fix it on the next release


for now you can put #_:clj-kondo/ignore in front of the offending symbol

Lukas Domagala19:11:06

i guess i could use a macro to only spit out the debux version if the clj version of the require also exists, but that seems like overkill

Lukas Domagala19:11:50

i’ll make an issue and try to get shadow to not be pissed at me. thanks for the help!

Lukas Domagala19:11:51

ah btw i have the same clj-kondo problem in clj, do you want it in the same issue?

Lukas Domagala19:11:25

(def debux-enabled?
       (require 'debux.common.util)
       (when debux.common.util/result*
       (catch Throwable _ false)))
clj version


clojure does not support the above I think

Lukas Domagala19:11:11

are you sure? seems to work for me or at least it compiles

Lukas Domagala19:11:19

ill run it, let me check

Lukas Domagala19:11:54

works in the repl


try it in in a standalone file


and then run it from the command line


it will fail


you cannot use a fully qualified symbol like that. clj-http doesn't do that

Lukas Domagala19:11:20

ah so you mean the require will work but the usage will fail? that makes sense

Lukas Domagala19:11:30

mhh, seems like a lot of work wrap everything with resolves


you only have to wrap it once and then call the wrapper

Lukas Domagala19:11:54

@U04V15CAJ that’s great, thanks so much!


may I suggest flipping the entire exists logic? ie. instead of checking if something exists you have that something register itself on load


so you have (ns your.lib.registry) with (defn register-thing [whatever] ...)


and the "conditionally loaded" thing just registers itself when loaded


at runtime you can just check if the thing did register itself without mucking arround in global namespaces and such?


You can do that if you control the optional namespace


you can by just creating an extra namespace that bridges it 😉

Lukas Domagala08:12:37

unless my brain is foggy because I just woke up, but wouldn’t I have the same “optional” problem in the other direction now?


point is you have a (some-ns/do-something) function somewhere that you call


and it does something different depending on whether a thing registered itself or not


but it only checks its own registry and not some namespaces and such


given that namespaces don't really exist in CLJS anything related to them is icky to say the least


Yeah you can make another optional namespace that you do control and then register something.


if its about debugging and stuff :preloads is usually the place where you want to load "optional" stuff

Lukas Domagala08:12:07

ah ok yeah I get your method. that’s how I’d do it if I had a DI container in a different language. my problem is that the optional lib doesn’t know anything about the main lib, so to do the registration i’d still have to do some magic

Lukas Domagala08:12:27

but yeah the final interface would be a little less magic, so thats good at least


no magic needed really since that "adapter" namespace you create can just do whatever and doesn't need to worry about anything conditional


the only problem really with all of this is :advanced not being able to detect if the conditional thing is actually loaded or not. so the calls to anything optional are not removed as they are not DCE


but there really is no easy way to solve this

Lukas Domagala08:12:16

well, i still need a way to know if i want to load your “browser” or the “react-native” ns if we are talking about your gist


that is handled by the build config

Lukas Domagala08:12:38

and i’m fine with breaking advanced compile, it’s a dev time lib anyway


ie. the :browser build obviously doesn't load the :react-native ns


no I mean say you write a logging lib of some sort


so you have (that-ns/log :something {:foo "bar"}) or so everywhere in your code


but the conditional thing is not loaded so log doesn't do anything and is technically dead code


DCE :advanced cannot detect that so it remains intact

Lukas Domagala08:12:07

well yeah, but that would be pretty tiny + a wasted call to a no op

Lukas Domagala08:12:01

but is there no decent way to detect if i should do :browser or :react without a config file? that’s what i was trying to avoid


don't know what you are trying to do exactly so can't say much more. conditional require in CLJS is not an option like it is in CLJ

Lukas Domagala10:12:44

thank you anyway! don’t want to waste too much more of your time, so ill play around with it more by myself for some time. if it’s ok I’ll check back in with the final result to see if I did anything too awful ;)