Fork me on GitHub
#clojurescript
<
2017-11-02
>
cmal06:11:12

Hi, how to make goog.debug.ErrorReporter work in ClojureScript? I added this to my code and it did send a POST request. But when the page get errors in js it did not send POST requests.

(defn install-error-reporter
  []
  (let [reporter (.install goog.debug.ErrorReporter error-reporter-url)]
    (.sendErrorReport reporter "safdsf" "safsdfsaf" 16)))

genRaiy09:11:02

quick question on using nodejs with clojure … how do I obtain the value of an env variable?

genRaiy09:11:41

I know it’s on the nodejs process object but it doesn’t seem to dereference ‘env’

genRaiy09:11:55

for example (.-env js/process) gives back an object

genRaiy10:11:13

but I don’t see how to examine that object … I’m probably missing something obvious

pesterhazy10:11:51

Javascript question. I'm looking for the equivalent of (doto x js/console.log) in pure JavaScript. Is (function(v){console.log(v);return v;})(x) the best I can do even in modern JS?

pesterhazy10:11:29

(especially if x is actually a more complicated expression)

genRaiy10:11:21

@metametadata yay! thanks that’s perfect

genRaiy10:11:54

[ also quite glad it wasn’t that obvious ]

p-himik10:11:43

@pesterhazy In somewhat modern JS: (v=>(console.log(v),v))(x)

pesterhazy10:11:18

@p-himik aha, the comma operator

pesterhazy10:11:10

I never knew there was such a thing

Hendrik Poernama12:11:52

Is there a way to guarantee a namespace is loaded before anything else? Preload doesn't seem to do it. Context: cljs is loading the process.env shim after some node_modules that needs it, causing 'process is not defined' errors. These node libs don't explicitly require it, which I think confused the dependency sorter.

Hendrik Poernama12:11:41

Now I have to define it in the html :thinking_face:

p-himik12:11:08

@poernahi I've created an issue for that: https://dev.clojure.org/jira/browse/CLJS-2393 As of the solution, I didn't find any except for delaying the inclusion of code that requires process.env.

Hendrik Poernama12:11:13

hmm.. interesting

Hendrik Poernama12:11:15

so, if I manually add process.env on top of the preload list, it should work? time to test...

p-himik12:11:21

Hm, for some reason this solution did not occur to me at all. 🙂 Let us know what you'll find.

Hendrik Poernama13:11:44

thanks for that link

Hendrik Poernama13:11:49

wow re-frame.trace is awesome

p-himik13:11:35

Indeed it is. But beware of a big app-db - tracing can get quite slow.

maleghast13:11:04

Can anyone explain what this means (from the CLJSJS website): “You can now use your newly added library by accessing it through the global Javascript namespace, e.g. js/React. Please check the project’s documentation to find out what global the library uses.” and further to that, does anyone have any example code they can share of using recharts via CLJSJS in clojurescript, please?

maleghast13:11:41

I am very__ new to clojurescript, but I have a solid JS grounding, so the examples on the recharts website for JS 1.7 make sense - it’s just that now I need to figure out how to do the same things in ClojureScript…

mfikes13:11:29

@maleghast js is a pseuso-namespace (or a "magical" one), that essentially provides access to the global JavaScript scope. So, for example, js/console refers to the global console object.

maleghast13:11:59

@mfikes - Ah ok… So once I’ve added the package for recharts to my build.boot and required it in the cljs namespace where I want to use it, I need to figure out the right global object for recharts..?

Hendrik Poernama13:11:47

so in your case, I think it would be js/Recharts

mfikes13:11:11

@maleghast Essentially, yes. Oftentimes you use js/ interop to access a library via a global that it has established

maleghast13:11:47

@poernahi - Right, thanks 🙂

maleghast13:11:50

@mfikes - OK, that makes sense…

maleghast13:11:06

Unfortunately I am getting an error when I try to :require the library…

mfikes13:11:48

@maleghast What error? By the way, https://clojurescript.org/guides/quick-start#dependencies is probably worth a read if you haven't done so already

maleghast13:11:10

@mfikes - I think I’ve sorted it; I thought that my environment would grab the dependency all by itself but apparently not… I stopped my app and re-started it and I am getting messages in my console about the relevant dependencies being retrieved now.

mfikes13:11:41

Ahh, right. Need the JARs to be on the classpath 🙂

maleghast13:11:20

I am feeling the n00b thing, pretty hard, but I have to say that I am finding cljs easier than the last time I looked at it…

chrisetheridge13:11:02

has anyone found that their cljs builds, using lein-cljsbuild do not exit on WARNINGS? for instance, a warning such as Wrong number of args passed to ... shows up as a WARNING, but surely the compiler should exit at a warning like that? that is broken code

mfikes13:11:31

@biscuitpants There is definitely a philosophical stance taken that warnings are not fatal. Perhaps there is a good reason arity problems are deemed warnings in ClojureScript (while not so in Clojure)—perhaps related to the way the JavaScript host behaves.

chrisetheridge13:11:15

that is understandable, but is there a way to configure it to exit on these warnings? i’ve tried using the warning handlers hook, but i would need to filter out a lot of false positive warnings, which is also a brittle way to solve this problem

mfikes13:11:32

@biscuitpants Yes. You can take a specific warning and essentially cause it to be fatal. In other words you could specifically make arity warnings fatal.

chrisetheridge13:11:52

via the warning handlers, like i described above?

chrisetheridge13:11:24

ah, okay. hopefully there is more concrete support for this in the future. maybe a way to set the level of warning on which the compiler exits?

mfikes13:11:52

@biscuitpants Here is an example I use when building Planck. I chose to white-list the ones I want to be non-fatal, but you could employ any logic you'd like: https://github.com/mfikes/planck/blob/master/planck-cljs/script/build.clj#L26-L27

chrisetheridge13:11:12

thank you! that is a great start

mfikes13:11:45

All you need to do is take a gander at cljs.analyzer/*cljs-warnings*

mfikes13:11:32

I suspect :fn-arity is the one you are specifically interested in.

chrisetheridge13:11:53

haha so we are doing exactly what you are doing, except using regex’s at the moment. using keywords would be much better, so thank you!

mfikes13:11:28

Oh, right. Yes, using concrete keywords instead of regex's on the strings is mas bueno

chrisetheridge13:11:48

very much so. thank you, i really appreciate the help @mfikes

mfikes14:11:11

FWIW: My recollection of the philosophy / stance (from a discussion with David on IRC a few years back) goes along the lines of: If it is at all possible for the analyzer to actually analyze the code and produce a well-formed AST, then it will do so, while at most emitting warnings. The analysis step will only fail if it simply cannot analyze what has been read. This results in a bit of looseness that caters to the Lispy dynamic nature of things at the REPL, thus facilitating, for example, seeing an arity warning, and then either changing the call, or changing the target function. In other words, it is fairly conservative, so long as it can generate an AST that the compiler can use to generate legit code, letting you as the developer decide what to actually do when warnings are emitted. This also makes it possible to see all of the analysis warnings in a given compiled namespace without it blowing up prematurely.

chrisetheridge14:11:58

yeah, i understand that there needs to be some catering done, because of Lisp. it is nice to see all of the warnings at once, without having each warning blow up the process

wpcarro15:11:22

Can any Garden users in here help me create padding settings? I’m currently defining padding using a vector like [(px 1) (px 2)]… but my output styles are comma-separated values like padding: 1px, 2px which Chrome isn’t recognizing as valid CSS

wpcarro15:11:59

any help here would be greatly appreciated bc I recently ported most of our existing styling over to Garden and now we’re suffering from styling regressions, which is unfortunate… I cannot seem to find anywhere in the docs that point to the proper way of handling this

roosta16:11:54

@wpcarro It might not be the solution you're looking for but what I usually do if I need to define multiple padding values using shorthand is just use a string:

:padding "0 0 10px 0"
and if I need some variable in there I'd do this:
:padding (str "0 0 " (px my-variable) " 0")
Not very elegant but like you pointed out garden handles vector input a bit differently than say JSS, where using an array is valid.

wpcarro16:11:52

@roosta hmm I had a lot of code like that originally, but it breaks down for thing like box-shadow shorthand… imagine you need to encode x y blur and color… how can you stringify garden colors?

wpcarro16:11:44

all of the colors defined in my styles are (color/hsl 180 100 50) format

wpcarro16:11:53

and when you call (str ...) on these you get outputs like

(str (color/hsl 100 100 100))
"garden.color.CSSColor@f9ec246b"

wpcarro16:11:12

and then your CSS breaks

roosta16:11:54

hmm, I haven't really used the color functions in garden a whole lot. I just asssumed they retuned a string but clearly not.

wpcarro16:11:36

yea unfortunately you need to call (render-css ...) on them to get usable strings

alexisvincent16:11:45

Does clojure promise not exist in clojurescript?

alexisvincent16:11:22

Oh damn, that explains things. Kept getting undefined

wpcarro16:11:31

maybe Garden should expose a shorthand function that can automate a lot of this. I think this only breaks down in shorthand definitions anyways, so maybe that’s a clean fix

kasuko16:11:24

Hey, I am working on packaging a javascript library for use in clojurescript. I want it to work as if I had provided the :npm-deps requirement but while using the :foreign-libs (e.g. I can use (:require [my.components :as components]) Is this possible?

kasuko16:11:29

Note: My javascript library is not globally loaded, so I can not use the :global-exports key

roosta16:11:51

@wpcarro sounds like a good idea, but as far as a solution to your predicament, i don't rightly know. your guess is as good as mine. A macro could maybe simplify the shorthand syntax, by wrapping render-css or something

dominicm16:11:31

@kasuko as far as I know, that can be done, yes.

wpcarro16:11:46

@roosta thanks for the feedback!

roosta16:11:04

@wpcarro not a problem, sorry i couldn't be of more help

dominicm16:11:04

@kasuko https://clojurescript.org/guides/javascript-modules#javascript-modules this example is es6, but should be easy to update for commonjs if you're using that.

dominicm16:11:31

I did run into https://github.com/google/closure-compiler/issues/2634 when I tried to use it though (for commonjs)

dominicm16:11:12

It seems that you're using React, if you've got JSX in the mix, you should also see https://clojurescript.org/guides/javascript-modules#babel-transforms

wpcarro16:11:13

@roosta take a look at this if you’re interested! https://github.com/noprompt/garden/issues/15

roosta16:11:05

@wpcarro that seems but address at least the comma separated shorthand issue. nopromp mentions using [[]] for space separated, did you try that for the padding?

wpcarro16:11:03

@roosta yea it works… it’s great. I’m going to submit a PR later this week to augment the docs because it isn’t very clear

roosta16:11:47

nice, good luck!

kasuko16:11:56

@dominicm Thanks, that got me a little further, however it’s actually a UMD module and when I try to load it in it fails to load the the ‘react’ and ‘react-dom’ modules. I do have :requires ["react" "react-dom"] in my foreign-libs

kasuko16:11:49

Maybe a better way to get this to work would be to force my UMD module to load itself into the global namespace. This works fine if I am running it without :optomizations but as soon as I try to compile it with the :optimizations it no longer loads in the global namespace

thheller17:11:08

@kasuko if your lib is pure JS and only has JS deps you could publish it to npm

Hendrik Poernama17:11:07

speaking of UMD modules.. Can anyone help me understand CLJS-2327? cljs now prefers browser instead of module from package.json. In the lib I'm using (react-apollo), browser points to react-apollo.browser.umd.js while module points to index.js which uses ES6 exports/import. CLJS was able to consume index.js, but breaks on the umd because the umd is trying to pull some global names like window.React which is exported as some$long$path$React. I want to file a bug, but I'm not sure if the problem is CLJS, rollup (the packager that writes umd) or react-apollo (the one who writes package.json). I don't know enough about modern js packaging...

Miloslav18:11:26

Hello everyone!

kasuko18:11:41

@thheller I wish, it’s my companies private component library. However I figured out the issue, since I control both the JS and the CLJS I was trying to sneak the CLJS wrapper in the same namespace as the JS library.

kasuko18:11:11

So under advanced compilation the namespace of the wrapper was clobbering the top level var that the library was in

Miloslav18:11:20

Could you please help me? What if I want each re-frame page or component to be in separate files but in same namespace?

Miloslav18:11:10

Is it possible? The component is function with its own name, and if it needs its own namespace, the component usage looks like this: components.my_component.my_component, and that's not great

noisesmith18:11:20

that's possible in clj, I think it's possible in cljs (though trickier), but it's usually nota good idea

noisesmith18:11:44

this is what the :as arg to require is for - to get shorter aliases to other namespaces

Miloslav18:11:30

So I need to explicitly require each and every component in order to use them?

noisesmith18:11:54

that's the normal way to do things, using other namespaces and not requiring them is a very bad idea

noisesmith18:11:37

the require block should help someone who reads your code to know what other code it depends on, and where to go to find it

Miloslav18:11:17

But I want them to be used like components.foo and components.bar, and its possible only if the components are defined in same file

Miloslav18:11:53

I want to just require components and maybe refer what's needed

noisesmith18:11:08

that's not how clojurescript or clojure is typically done. It's possible but it will be weird, and there's problems with working that way.

noisesmith18:11:19

it's a relatively opinionated language

Miloslav18:11:25

Okay, so is it possible to just concatenate cljs files? Maybe via leiningen

Miloslav18:11:54

I really need my components to be used exactly that way

Miloslav18:11:57

So how is it typically done? Reframe Boilerplate puts all the components in one single file, and that's not how you make your app scalable

darwin18:11:13

@melvoloskov what about letting them sit in their current location and then introduce a new namespace having just references to those long component vars?

darwin18:11:56

e.g. in components namespace do (def my-component components.my-component/my-component)

Miloslav18:11:59

Is there something like export default in cljs?

Miloslav18:11:27

Yep, that's how I do it now

noisesmith18:11:45

one of the best things about clojure is making scope and bindings explicit and non magical, anything that works around this is undermining one of the language's best features IMHO

darwin18:11:02

so what is the problem? keeping it in sync?

Miloslav18:11:06

You're right. explicit definition is trusty

darwin18:11:10

you can go fancy and use a macro to generate that aux namespace defs by walking defined stuff in source namespaces

Miloslav18:11:22

By the way, re-frame uses case to define a page to show, but I just want to replace it with something that takes page's name and looks it up in pages namespace, and if it's found, it just returns that page, and if it's not, it returns the predefined page, for example 404 page

Miloslav18:11:34

But I don't know how to do that

Miloslav18:11:24

Because if you want to add a page, you need to do the following: 1. Define page component 2. Define it's route 3. Define page's name into that case why not to omit third step to make the code more dry?

darwin18:11:55

you should ask in #re-frame channel

Miloslav18:11:19

Oh, I didn't knew about it

Miloslav18:11:28

Thank you very much!

Miloslav18:11:45

How do make the keyword from a string?

noisesmith18:11:14

be careful with keyword, it will happily generate nonsense

+user=> (keyword "                            lmn           p")
:                            lmn           p

Miloslav18:11:50

Thank you again

noisesmith18:11:26

if the data is coming from a string at runtime, it often makes sense to use strings instead of keywords in the first place (cljs will happily use strings as keys in hash maps etc.)

Miloslav18:11:41

So I can do

(defn foo [a] (+ 1 a))

(println ((keyword "foo") 2))

=> 3 
?

noisesmith18:11:05

keywords aren't functions

noisesmith18:11:19

well, you can call them, but they don't refer to functions you have defined

Miloslav18:11:21

I meant function names

noisesmith18:11:31

yeah, keywords are not for that at all

noisesmith18:11:48

you can use resolve / symbol to find a function by name, but it's usually a sign you are making a mess if you resort to such things

Miloslav18:11:49

Keywords are keys for maps?

noisesmith18:11:55

it's needed by tools like lein though

noisesmith18:11:09

keywords are a data type that stands for itself and has a readable name

noisesmith18:11:12

that's what they are for

noisesmith18:11:18

like an enum

dpsutton18:11:45

keywords are often used for maps but clojure will happily hash anything and use it as a key

noisesmith18:11:16

+user=> ((resolve (symbol "+")) 2 2)
4
- this works, but is a good way to end up with a mess

dpsutton18:11:43

for when you want to hijack what + means, which is not really a good idea 🙂

noisesmith18:11:14

it was an arbitrary choice of function that everyone knows what it does and knows the answer is correct

noisesmith18:11:23

tools like lein use this to start your clj project

Miloslav18:11:30

Yes, you're all right again

Miloslav18:11:25

It's about explicit requiring, just like the previous questions

noisesmith18:11:36

you're catching on 😄

noisesmith18:11:08

we do have things for dependency injection - eg. defmethod and defprotocol to define things that can be extended by other code

noisesmith18:11:22

and you can get a new behavior by defining a new extension of the method or protocol

noisesmith18:11:51

but usually pure functions plus immutable datatypes is the path to glory with clojure

Miloslav18:11:56

I'll dig it right now

Miloslav18:11:22

Wtf this is pure oop

noisesmith18:11:47

not quite - for example you can extend a protocol you don't own to a class you don't own

noisesmith19:11:03

it's runtime extension, using some of the same approaches OOP uses

noisesmith19:11:11

but once again, pure functions and immutable data are usually the right choice, and it's best to stick with those until you realize you need those other structures

qqq21:11:34

goog.object/get <-- does using this get around all the cljs optimizations renaming issues ?

phronmophobic21:11:12

you’re referring to try to grab a property from an object that you know will be there at runtime?

phronmophobic21:11:08

seems like goog.object/get should work. I’ve used aget before, but i’m not sure it’s the “right” way to do it

phronmophobic21:11:47

ok, using aget is not the right way

dnolen21:11:44

yes goog.object/get is preferred

qqq23:11:18

https://www.html5rocks.com/en/tutorials/getusermedia/intro/ <-- is there a cljslibrary that wraps getUserMedia ?

madstap23:11:05

I trying to use a typescript library with :npm-deps and I'm using https://github.com/binaryage/cljs-oops to access functions and stuff with oget and ocall, but this doesn't work with advanced optimizations. I can print the object that serves as the "namespace" of the library at runtime, but the call (ocall PrismicJS :api url) returns an api object with optimizations :none and returns null with :advanced. Where should I start looking here?

madstap23:11:27

And, in general, do I still need to generate externs when I use cljs-oops for all my calls to libs in :npm-deps?

darwin23:11:22

@madstap no, by using cljs-oops you don't need to write externs

darwin23:11:49

"No! Use oops only for interop with external code which is not part of your :advanced build. That means for all code where you would normally need to write externs."

darwin23:11:49

"Gluing it all together is the :npm-deps compiler flag. In it, we tell the compiler which dependencies it should be aware of. ClojureScript will take care of installing those dependencies and running them through the Closure Compiler conversion pipeline, including optimizations which we describe in more detail below."

darwin23:11:23

that sounds like :npm-deps stuff goes through :advanced optimizations, so you should not use cljs-oops with it