Fork me on GitHub
#clojurescript
<
2018-10-27
>
kwladyka09:10:30

How to check during compilation time if should I make atom using: reagent.core/atom or atom. I wrote library which make atom to validate-form, but I would like to have it compatible with the most popular libraries. So if somebody use reagent I want to make atom using reagent.core/atom, if not use atom.

mfikes10:10:54

@kwladyka you could allow the user to configure it via :closure-defines

kwladyka11:10:47

it is one of the option, but I would prefer over it detect if developer use reagent or not and then use right one

kwladyka11:10:07

anyway as I understand this value can be string / number / boolean so I can’t refer to right atom function

lmergen12:10:53

i guess this question is more broadly related to javascript in general, but what is a good strategy for having different types of endpoint configurations in the clojurescript code depending upon which environment it is being deployed in ? the most obvious solutions i can think of is providing an argumen to the build (thus hardcoding endpoints in the javascript, suboptimal), or to assume the host that serves the js bundle has $some endpoint that provides configuration data (like an /config endpoint, an additional round-trip, but more flexible)

lmergen12:10:07

any other strategies that work well ?

lmergen12:10:17

the last i thought of was "just-in-time" compilation of all clojurescript code and injecting the endpoints dynamically that way, but this is also suboptimal for various reasons

dnolen12:10:11

I don't see why setting this via the build is suboptimal

lmergen13:10:52

but then you would need to know the endpoints that will be used in advance, not ?

lmergen13:10:29

i.e. you cannot deploy the same code in multiple environments

lmergen13:10:32

(fwiw, i am totally not a frontend developer, so i'm approaching this from a backender's perspective)

mfikes13:10:50

Krzysztof’s question was regarding compile time—for this :closure-defines is ideal

dnolen13:10:00

@lmergen you can build N times for each environment

dnolen13:10:21

pretty standard practice

lmergen13:10:43

it's the simplest i guess

dnolen13:10:44

:closure-defines is all you really need

kwladyka15:10:07

@mfikes why not macro?

kwladyka15:10:18

> In those situations, it is recommended that libraries and tooling employ goog.define instead, perhaps with the help of :closure-defines, as this makes JARs cache-friendly. Oh so it is only one option then. Right?

kwladyka15:10:31

No alternatives.

dnolen15:10:01

yes - it's just the right and supported way to do configuration

mfikes15:10:36

goog-define will create a specially-handled var in a namespace of your choosing and you can document the qualified symbol for consumers of your library to use with :closure-defines

mfikes15:10:28

You can then write conditional code testing that var’s value which will effectively be done at compile time if the library consumer is using :advanced, all while being compatible with :aot-cache

mfikes15:10:25

I suppose for the Reagent atom case, on one branch of the code you would use interop to construct a Reagent atom

mfikes15:10:56

(Assuming your library isn’t actually requiring Reagent itself)

lilactown15:10:49

as a consumer of a library, I would much rather pick which one to use

dnolen15:10:04

stuff that creates problems for future leverage of :aot-cache should just not be under consideration

dnolen15:10:40

we need to stop using macros unless we absolutely need them

kwladyka16:10:31

thanks for explanation

hoertlehner20:10:54

Is there any way how I can return multiple values for a reagent function? In Javascript there is a special element that does not get rendered to the dom, so similar to a div, but not put into the dom. I just cannot find this approach for reagent. Any ideas?

lilactown20:10:00

@andrea.crotti in #reagent you can use fragments just like in regular React

lilactown20:10:49

the hiccup is :<>, e.g.:

[:<>
  [:div "foo"]
  [:div "bar"]]
which is the same as:
<>
  <div>foo</div>
  <div>bar</div>
</>
in JSX

hoertlehner20:10:37

thanks so much!

hoertlehner20:10:58

I haven't been able to find the :<> symbol 🙂

lilactown20:10:22

yeah I’m looking for the correct docs rn

lilactown20:10:43

reagent is not very organized. a lot of the docs are in the re-frame repo too 😅

hoertlehner20:10:01

I just learned re-frame yesterday,

hoertlehner20:10:03

and I love it.

hoertlehner20:10:16

The syntax is so precise; my react/redux apps they are blown up on I think 10 files, just for a basic app.

hoertlehner20:10:30

And with re-frame, all the code is so clear to understand, and very short.

hoertlehner20:10:41

But docs, this is the huge missing thing.

hoertlehner20:10:56

I spent I dont know how many days, just to get a few material-ui components going,

kwladyka21:10:28

This is separate thing from re-frame.

kwladyka21:10:53

Not blame re-frame doc about that. Nothing to do with this.

kwladyka21:10:27

BTW you can check this branch https://github.com/kwladyka/form-validator-cljs/tree/doc It shows how to use figwheel-main with material-ui in the best way what I know. But this code is under have development. Not finished yet.

kwladyka21:10:48

But it should help you a lot with using js deps like materia-ui with cljs.

kwladyka21:10:28

I hope I will finish this code in 1 week

kwladyka21:10:30

Look on: webpack.config.js, figwheel-main.edn, src/js/index.js

kwladyka21:10:43

You don’t want to use cljsjs packages. size is too big, no optimisation. Always issue with versions etc.

kwladyka21:10:53

At least I can recommend you how I am doing this.

kwladyka22:10:05

PS Node dependencies with ClojureScript is hard topic.

hoertlehner20:10:09

and I haven't even had a look at more complex material-ui componets.

kwladyka21:10:02

{:names->value {:email ""
                                  :password ""
                                  :password-repeat ""}
                   :names->validators {:email [::sc/email]
                                       :password [::sc/password]
                                       :password-repeat [?password-repeat]}}
(-> @form
              (pprint)
              (with-out-str))
pprint show function as #object. Any way to show map exactly as it is defined? With fn name instead #object.
{:names->value {:email "", :password "", :password-repeat ""},
 :names->validators
 {:email [:form-validator-demo.spec/email],
  :password [:form-validator-demo.spec/password],
  :password-repeat
  [#object[form_validator_demo$views$_QMARK_password_repeat]]}}

bbrinck22:10:23

What’s the recommended way for a library to opt-in to accessing private variables without triggering a warning? My understanding is that future versions of CLJS will have a warning for private variable access (which is great!) but I’m not sure how to write code that will work both before and after ana/*private-var-access-nowarn* is introduced

bbrinck22:10:22

If I try to always bind ana/*private-var-access-nowarn* true, then that will produce a warning in older CLJS versions. But if I omit it, then presumably the private var access will trigger warning in upcoming versions of CLJS

mfikes22:10:54

@kwladyka the issue is that it is printing a function value, which has never really had a decent way to print how that value was defined. One option is to (set! *print-fn-bodies* true) to see the JavaScript implementation of the function value

kwladyka09:10:33

{:names->value {:email "", :password "", :password-repeat ""},
 :names->validators
 {:email [:form-validator-demo.spec/email],
  :password [:form-validator-demo.spec/password],
  :password-repeat
  [#object[form_validator_demo$views$_QMARK_password_repeat "function form_validator_demo$views$_QMARK_password_repeat(form,name){

var password = cljs.core.get_in.call(null,cljs.core.deref.call(null,form),new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Keyword(null,"names->value","names->value",-1214004968),new cljs.core.Keyword(null,"password","password",417022471)], null));
var password_repeat = cljs.core.get_in.call(null,cljs.core.deref.call(null,form),new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Keyword(null,"names->value","names->value",-1214004968),name], null));
if(cljs.core._EQ_.call(null,password,password_repeat)){
return null;
} else {
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Keyword(null,"password-repeat","password-repeat",-152826064),new cljs.core.Keyword(null,"password-not-equal","password-not-equal",-394108947)], null);
}
}"]]}}
Now it looks like that 🙂

mfikes22:10:30

(I’m presuming you are dealing with a function value—perhaps it is actually some other object type.)

mfikes22:10:51

@bbrinck you could use the var special

bbrinck22:10:31

@mfikes Hm, I’m afraid I’m not sure how to use that in a binding form. I want to do something like

(binding [ana/*private-var-access-nowarn* true]
  ;; some private var access  
)

bbrinck22:10:59

do you mean I should wrap ana/*private-var-access-nowarn* in var e.g. (var ana/*private-var-access-nowarn*)?

mfikes22:10:20

I just mean, do it like you would in Clojure. So, for example you could do

#'clojure.string/replace-all

mfikes22:10:50

This leads to a little var bloat in the generated JavaScript.

bbrinck22:10:53

gotcha, you’re saying I should just use #' to access the private function (like in CLJ) instead of trying to mess around binding a (possibly non-existent) dynamic variable like ana/*private-var-access-nowarn*

bbrinck22:10:50

good idea, it looks like that worked. thanks!

mfikes22:10:02

Well, since you mention that dynamic var, it makes me think I may not be understanding what you are doing, maybe you are in Clojure

bbrinck22:10:33

Sorry, dynamic var is likely the wrong term in CLJS

bbrinck22:10:44

To zoom out a little, I want to call a private function in CLJS without issuing a warning, regardless of CLJS version (I understand I’m depending on implementation details, and I’m ok with that)

bbrinck22:10:21

My first idea was to just call the function directly and wrap the call in (binding [ana/*private-var-access-nowarn* true] ,,,), which AIUI, would avoid the warning in new versions of CLJS

bbrinck22:10:53

but now I’m going to try just using #' to call the private function, as you suggested. I’ll let you know how it goes.

mfikes22:10:33

And vars in operator position are automatically derefed so no need to use @

bbrinck22:10:08

Perfect, that’s super helpful. Thanks!

borkdude23:10:01

is it possible to write a macro that instruments something at the start some body given as an argument and unstruments something at the end reliably in clojurescript? there seems to be something going on with instrument/unstrument at macro compilation time

dnolen23:10:45

It can probably work, but instrument/unstrument is very static currently due to trying to support advanced compilation

dnolen23:10:45

It can probably work, but instrument/unstrument is very static currently due to trying to support advanced compilation