Fork me on GitHub
#clojurescript
<
2021-11-30
>
olaf09:11:13

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
  [company-name
   company-logo])

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

p-himik09:11:56

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
olaf09:11:19

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

p-himik10:11:44

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

mateus.henrique.brum14:12:08

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ā€¦

martinklepsch18:11:44

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

lilactown19:11:14

lots of node dbs. i'd start there

martinklepsch19:11:42

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

lilactown19:11:22

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

lilactown19:11:35

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

lilactown19:11:05

but sqlite is hard to beat

martinklepsch23:12:23

I ended up using Google sheets lol

martinklepsch23:12:00

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

borkdude19:11:54

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

borkdude19:11:45

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

borkdude19:11:05

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?

borkdude19:11:26

e.g. for clojure spec alpha, the user has to require clojure.test.check first to use certain features. https://github.com/clojure/clojurescript/blob/6443518850d8e4f1e09be99d4669e8d4a5e893a3/src/main/cljs/cljs/spec/test/alpha.cljc#L258

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

borkdude19:11:59

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

Lukas Domagala19:11:24

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

borkdude19:11:02

clj-kondo should support this:

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

borkdude19:11:10

I'll fix it on the next release

borkdude19:11:37

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?
     (try
       (require 'debux.common.util)
       (when debux.common.util/result*
         true)
       (catch Throwable _ false)))
clj version

borkdude19:11:42

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

borkdude19:11:35

try it in in a standalone file

borkdude19:11:46

and then run it from the command line

borkdude19:11:48

it will fail

borkdude19:11:46

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

borkdude19:11:45

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

Lukas Domagala19:11:54

@U04V15CAJ thatā€™s great, thanks so much!

thheller07:12:15

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

thheller07:12:37

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

thheller07:12:57

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

thheller07:12:14

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

borkdude07:12:32

You can do that if you control the optional namespace

thheller08:12:13

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?

thheller08:12:56

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

thheller08:12:07

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

thheller08:12:27

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

thheller08:12:44

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

borkdude08:12:59

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

thheller08:12:26

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

thheller08:12:19

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

thheller08:12:28

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

thheller08:12:49

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

thheller08:12:30

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

thheller08:12:49

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

thheller08:12:05

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

thheller08:12:24

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

thheller08:12:45

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

thheller08:12:58

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

thheller10:12:03

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 ;)