Fork me on GitHub
#clojurescript
<
2017-06-04
>
souenzzo02:06:31

How to get into graphs in clojurescript? I'm using ubergraph to describe some control structures of my system and in the moment, I plot from repl with uber/viz-graph. I want to put it in a "admin pannel" in clojurescript. But I didn't find: - how to/what format use to export graph (with metadata) from back to JSON/EDN/transit - how to plot it in clojurescript. There is some stuff on cljsjs but each lib has it own input format for graphs...

thedavidmeister08:06:30

@souenzzo depends a lot on your needs. If you're happy with something generic looking and aren't sweating the details, then just hit up cjsjs and search for "chart"

thedavidmeister08:06:11

if you want to make something more bespoke, I've had an OK time wrapping the lower level utilities of d3 to calculate things like scaling x/y positions and then rolling my own SVG elements with attributes

thedavidmeister09:06:07

or, to put it another way, there is no "standard chart library" that works for everyone in javascript, so there isn't one in cljs either, so there is no "standard chart input format" either 😞 - although there certainly are some efforts to do so, such as d3 and https://vega.github.io/

Oliver George11:06:09

Clojurescript on Windows users. Please vote on this. https://dev.clojure.org/jira/browse/CLJS-2036

Oliver George11:06:26

It looks like a compile bug associated with the :preloads feature. Stops us from using the more recent stable releases of CLJS.

dnolen11:06:23

@olivergeorge we have a very small number of contributing devs on Windows machines, happy to see that one fixed but you’ll probably have to provide a patch yourself. Pretty sure this is likely a file system issue, that’s been most of our problems on Windows.

urbank15:06:46

Pretty set on clojurescript at the moment, but does anyone here have any experience/views on ScalaJS?

drcode15:06:52

Hi, can someone give me advice as to the best way to give a sizable financial contribution towards clojurescript development? I don't see any info on this in the github page or the http://clojurescript.org site.

qqq15:06:12

I believe @dnolen is the lead dev. He could probably point you in the right direction.

drcode15:06:50

@qqq :thumbsup: I'm reachable at <mailto:[email protected]|[email protected]> if @dnolen or anyone else wants to get in touch

qqq15:06:36

@drcode : if you are throwing $$$ at clj/cljs, another project worth looking at is: https://github.com/clojure-emacs/cider ; they have detailed "funding" page at the bottom [disclaimer: I use cider; I am not a dev of cider. I would benefit indirectly (via improved dev tools) but not directly (i.e. cider does not pay me.) ]

drcode16:06:10

@qqq I also use cider every day- I will keep that in mind as I plan things out.

john16:06:08

I'd also advocate throwing money at figwheel. Not sure if Bruce is soliciting, but he's providing an important service to the community IMO

drcode16:06:02

@john yes, already contacted bruce 🙂

peeja16:06:42

What's the simplest way to turn CLJS into JS? I'm trying to reproduce a bug, and I'd like to avoid a whole project setup if possible.

noisesmith16:06:10

@peeja that's one of the first examples in the clojurescript quickstart https://github.com/clojure/clojurescript/wiki/Quick-Start

noisesmith16:06:15

just requires cljs.jar

peeja16:06:48

@noisesmith Ha! I think I clicked every link on the wiki but that one. Thanks!

peeja18:06:56

It looks like when you take the value of a dotted interop form, say .aJSMethod, ClojureScript emits simply .aJSMethod

peeja18:06:16

So (println .aJSMethod) emits cljs.core.println.call(null,.aJSMethod), which is invalid JS

peeja18:06:22

Is that a known issue?

john18:06:47

Hmm, I'd expect to see quotes around .aJSMethod at least.

peeja18:06:24

I'm not sure what to make of this: when I put it into http://app.klipse.tech/, I get an analysis error, but also output.

peeja18:06:55

.aJSMethod alone gives the error and no output

john18:06:00

Unexpected token .

john18:06:17

the reader chokes on it

john18:06:01

printing a dot method, unassociated with any object or anything, I don't think would be expected to work.

john18:06:30

or, well, no the reader doesn't choke on it

john18:06:40

javascript's parser chokes on it

peeja18:06:45

Right, it shouldn't do anything useful, but it should break the build process correctly.

noisesmith18:06:49

the answer I expect to see there is that .aJsMethod isn't a valid form

noisesmith18:06:55

garbage in, garbage out

peeja18:06:57

Yeah, exactly

peeja18:06:08

Well, no, hopefully garbage in, error out 🙂

peeja18:06:16

Ideally, never garbage out

noisesmith18:06:21

clojure and clojurescript do a lot of silly things instead of outright rejecting inputs

noisesmith18:06:24

in a lot of contexts

noisesmith18:06:31

spec may change this in the long run...

john18:06:56

But there are probably a billion ways to cause a js parser error. Do we catch all of them?

peeja18:06:16

Why would the compiler ever output bad JS?

peeja18:06:23

except in the case of a bug

noisesmith18:06:25

I doubt we catch any of them - explicitly at least

john18:06:55

It's not compiling, with println

peeja18:06:14

How is it not compiling?

john18:06:28

(println .something) is not "emitting" js

peeja18:06:48

No, no, that form is compiled, and the compiler emits bad JS

peeja18:06:03

println could be anything

noisesmith18:06:10

see, this is why using cljs.jar make sense - you can say that with a specific version of clojurescript we get this specific output...

john18:06:15

oh, how'd you get there?

ssaul18:06:42

@pedroteixeira did you ever solve your issue with running lein cljsbuild once hello once you cloned the om repo. I am still not able to figure out this clojure.lang.ExceptionInfo: Invalid :refer, macro cljs.pprint/deftype does not exist in file examples/hello/out/cljs/pprint.cljs {:tag :cljs/analysis-error} exception.

peeja18:06:45

For context, here's the bug surfacing in another issue, which is what led me down this rabbit hole: https://github.com/funcool/promesa/issues/48

peeja18:06:40

Now, granted, Promesa's macro acrobatics here may not be completely thought out, but it shouldn't be able to emit invalid JS

noisesmith18:06:40

$ cat src/repro/repro.cljs 
(ns repro.repro)

(println .fooBar)
$ rlwrap java -jar cljs.jar 
Clojure 1.8.0
+user=> (require 'cljs.build.api)
nil
+user=> (cljs.build.api/build "src" {:output-to "out/main.js"})
nil
+user=> 
$ cat out/repro/repro.js
// Compiled by ClojureScript 1.9.562 {}
goog.provide('repro.repro');
goog.require('cljs.core');
cljs.core.println.call(null,.fooBar);

noisesmith18:06:22

@peeja I'm going to take a wager that the cljs devs disagree with you, and that it's handy to reject invalid input, but there is no priority in cljs or clj dev to make erroneous output impossible

peeja18:06:46

Seriously?

noisesmith18:06:50

I could be wrong though, but I've seen similar responses to various other clojure / clojurescript behaviors when given erroneous input

peeja18:06:10

I would be extremely disappointed to hear that that was the case.

noisesmith18:06:27

"it does something invalid for this input" "that input wasn't valid so it's not a priority to fix it"

noisesmith18:06:44

it's a conversation I've had more than once with clojure devs

peeja18:06:03

Explicitly de-prioritizing error messages for problems that are obvious to the complier and non-obvious to the user is a great way to tank a language.

john18:06:35

Is this valid input: (.aJSMethod (js-obj))

noisesmith18:06:39

but is it obvious to the compiler?

noisesmith18:06:00

does cljs have the infrastructure to recognize valid vs. invalid js forms?

nikki18:06:05

but also you can impl it yourself if it's a lisp right

peeja18:06:09

Sure it's obvious. It does something special with (.aJSMethod (js-obj)). It doesn't do that with (foo .aJSMethod). Somewhere in the compiler there's already logic that says what to emit for that form, and that logic is incorrect.

nikki18:06:21

if there is a finite amt of time, it sounds more like they prioritize other things more, and the explicit deprioritization -> tanking argument may be a lot

peeja18:06:26

Why does it emit .aJSMethod?

nikki18:06:28

i generally give them benefit of doubt

peeja18:06:05

The analyzer already knows that that symbol can't be evaluated there. So why does it emit anything?

john18:06:23

how does it know?

john18:06:33

it's an interop

nikki18:06:35

does the analyzer run after full macroexpand only

noisesmith18:06:37

I bet it's related to the fact that (js/console.log ...) works

peeja18:06:40

It's not a valid interop form

noisesmith18:06:45

which is totally invalid as a clojure form

noisesmith18:06:56

but works (accidentally?)

john18:06:09

How does it know it's not a valid interop form?

noisesmith18:06:37

@peeja cljs doesn't assume a closed world where it knows what exists and what things mean in the output code

noisesmith18:06:49

it happily outputs things it knows nothing about

nikki18:06:52

atomically, (after macroexpand) there are a finite number or patterns to match interop forms against and it's not one of them @john i believe

noisesmith18:06:58

they are probably implemented by some other lib somewhere...

peeja18:06:13

CLJS just passes things through that it doesn't recognize?

peeja18:06:19

That doesn't sound right

noisesmith18:06:19

all the time, yeah

peeja18:06:23

Like what?

peeja18:06:29

debugger doesn't work

noisesmith18:06:29

usage of external libs

peeja18:06:44

There's an explicit reader form to emit raw JS

john18:06:45

The JS side handles a lot, obviously. Just like Java in Clojure.

peeja18:06:57

Otherwise, the analyzer expects to understand it

john18:06:00

It's a very host-dependent language.

noisesmith18:06:35

@peeja sure - but the compiler happily passes things through as is. I'm not objecting to the very idea of validating the compiler's output, but cljs has no such infrastructure or functionality right now.

noisesmith18:06:46

I'm not talking about what should be, but what is there.

peeja18:06:55

"but the compiler happily passes things through as is" -> Can you give an example?

noisesmith18:06:55

it's got near zero validation in place

peeja18:06:05

I'm not talking about validation at all

noisesmith18:06:15

@peeja as I said, pretty much any usage of a lib that isn't part of js

noisesmith18:06:21

it just passes through all your references

peeja18:06:39

Right, but symbols which begin with . are treated differently in CLJS

peeja18:06:44

Already, today

noisesmith18:06:51

only sometimes

nikki18:06:57

only when they are the operator right

nikki18:06:08

:thinking_face:

noisesmith18:06:09

eg. js/consolre.log - the clojure language says that shouldn't work, but because it's passed through it works

peeja18:06:17

Also, hang on, random symbols aren't passed through to JS at all

peeja18:06:20

That's just incorrect

noisesmith18:06:28

but we have evidence that they are

peeja18:06:39

Do we? What's that?

noisesmith18:06:44

I've never seen reason to beleive they aren't

peeja18:06:02

Have you ever seen anything else pass through directly to JS?

noisesmith18:06:07

I can emit calls to libraries that cljs.jar knows nothing about

noisesmith18:06:20

by putting them in the code

peeja18:06:21

Using js/, you mean?

john18:06:25

@nikki can you elaborate? re: a finite number of patterns?

peeja18:06:49

You can't just say Date and have that pass through to JS

noisesmith18:06:25

yes, that's true

john18:06:27

type .aJSmethod in the repl and it'll pass right though to the JS site, with an error coming from JS land.

nikki18:06:39

@john https://cljs.github.io/api/syntax/dot (x .y) doesn't match any of those patterns

peeja18:06:55

Yes, that is the one example we've got so far 🙂

john18:06:57

Because any dot prefixed form is potentially unknown to CLJS

peeja18:06:20

But dot-prefixed symbols aren't passed through to JS in any other situations

peeja18:06:24

only when they're illegal JS

noisesmith18:06:58

oh, otherwise they get converted, right

nikki18:06:22

i think it whitelists interop forms and does the interop, otherwise passthru

john18:06:43

@nikki I believe @peeja was saying that a (.x y) form was causing the erroneous output, when .x doesn't exist.

peeja18:06:08

When the compiler compiles (.aJSMethod something), it does become something.aJSMethod(), but the compiler's not just blindly passing the characters .aJSMethod through between something and (). It understands the JS it's constructing there.

nikki18:06:12

i thought that the macro changes it to the other form before js emit

peeja18:06:50

@nikki What I'm trying to say is that there's no other examples of passthrough, so I don't understand why that appears to be the fallback

noisesmith18:06:11

+user=> (macroexpand '(println .fooBar))
(println .fooBar)
fwiw

nikki18:06:12

:thinking_face: yeah i meant that as an accident of the current constructions

peeja18:06:15

If that were correct, you'd expect to see passthrough happen in other cases, producing correct output

nikki18:06:32

some times the way things happen isn't understandable with meaningful reason... lol

nikki18:06:18

@peeja whats the most macroexpand'd version of the bug example with p/alet?

peeja18:06:19

Which is why I think there must be a branch of the logic which already addresses this case, the only case where passthrough happens, which could throw an error, but instead says "ah, screw it" and emits the bad JS instead

john18:06:07

@peeja what do you mean "It understands the JS it's constructing there."? In what way?

nikki18:06:16

if u do (println x) doesn't it pass x thru or am i wrong

nikki18:06:51

r u saying it should know that .x is a bad form of JS identifier

peeja18:06:59

It doesn't, the analyzer figures out what x means. It could be a local or a var.

nikki18:06:19

if it's not a var, what happens

peeja18:06:24

If there's no local, it assumes it's a var

nikki18:06:33

ah its the other way round? ok

peeja18:06:45

Unless I'm wrong… checks

peeja19:06:15

cljs.user=> foo
WARNING: Use of undeclared Var cljs.user/foo at line 1
nil

peeja19:06:32

Yep, it looks for a var (and in CLJS, a missing var will evaluate to nil)

nikki19:06:55

we r guessing that based on an example

peeja19:06:12

So I'd understand more if it was looking for a var called .aJSMethod in the current namespace.

peeja19:06:28

But it's not, it just emits that name literally into the JS. Which is weird.

john19:06:18

Have looked into the guts of the analyzer and checked out what it is attempting to do with dot prefixed forms?

nikki19:06:45

(thanks @john for letting me know about app.klipse lol this is cool)

nikki19:06:06

on another topic: other than http://thi.ng and kovasb gamma, do y'all know some neat paradigms / libs for webgl on cljs?

nikki19:06:52

http://regl.party is data-oriented enough that it can be used from JS interop from cljs pretty well

john19:06:01

@peeja might want to bring it up in #cljs-dev. Like we've been saying, CLJS doesn't have a general policy of cleaning all garbage on the way in, which, as @noisesmith mentioned, may be improved on with spec in the future, but it couldn't hurt to ask them.

peeja19:06:02

Right, I understand that, my assertion is that I don't think this actually needs to be cleaned on the way in so much as handled differently where it's already handled. But I'll dig deeper.

rauh19:06:20

Frankly, I don't see the issue. The error is one level later. At compile time of the JS code. If this was a runtime error... I'd understand.

mobileink19:06:22

where is the most thorough explanation of js interop? i'm having to translate stuff like app.$.foo.bar(baz) or Polymer.dom(document).querySelector("#foo .bar"), and it's mostly trial and error. the explanations i've found online tend to treat only the simplest cases.

mobileink19:06:50

(I mean, for somebody who is not a js ninja.)

nikki19:06:48

:thinking_face: you could write a JS -> interop compiler lol

nikki19:06:02

also is there some resource that has listed all the cljs react wrappers and what they are about

peeja19:06:45

@rauh When I my CLJS compiles fine but I get a JS syntax error after I deploy my node app to the server because a library macro did something funny with a symbol, that's pretty obscure. I've already lost a lot of time on it.

peeja19:06:04

I feel like never emitting illegal JS (but certainly sometimes emitting legal JS that doesn't run) is a perfectly reasonable line to draw for a JS compiler.

peeja19:06:12

(or any compiler)

nikki19:06:39

yah... i mean for now u could run an analyzer on the js after js build step

mobileink19:06:30

that's my main resource, in fact.

noisesmith19:06:14

for chained expressions like you share, the thing I use that isn't in that guide (as far as I saw) is -> which makes literal translations from examples easier

noisesmith19:06:51

(-> app (.-$) (.foo) (.bar baz)) - the hard part is knowing when something is a property or method (.- vs. .)

noisesmith19:06:34

and since js makes no such distinction, that requires either trial and error, console examination, or reading docs

mobileink19:06:17

but i find it assumes a little more js-fu than i have. e.g. sometimes js/foo.bar works, and sometimes it doesn't. looking for a little more hand-holding, i guess. 😉

mobileink19:06:54

ah, i was looking for sth like that!

noisesmith19:06:32

js/foo.bar is sugar, and I don't really like it personally, it can always be replaced with (.bar js/foo)

mobileink19:06:58

ok, good, i don't mind trial and error as long as i know it's unavoidable.

mobileink19:06:34

separate issue: i've run into trouble with dashes and underscores. i understand aget and aset deal with this; what's best practice? always use aset/aget?

noisesmith19:06:34

dashes should only come up for things defined for and by cljs itself, which shouldn't be accessed via aget / aset usually

mobileink19:06:32

wait, we should not write (defn foo-bar...) in cljs?

mobileink19:06:56

mind you this is all in the context of interop. my cljs must play nice with a js "object".

mobileink20:06:46

i'm delegating from a js object to a cljs ns.

dominicm20:06:52

When doing macros in a .clj file, how can I refer to, e.g. goog.object?

mobileink20:06:27

the js object is initialized via interop, clj->js.

adamvh20:06:35

@dominicm if you want to interact with goog.object at run-time, just use the symbol goog.object in your syntax-quoted form

dominicm20:06:59

@adamvh so use everything via full namespace symbol? Feels awkward, but okay 🙂

adamvh20:06:49

well, so what happens is that if your macro returns a syntax-quoted form, all the symbols in that form will be prefixed with the namespace in which the macro is expanded

adamvh20:06:18

after the macro is expanded

adamvh20:06:08

so if you have (ns my.cls.ns :require [goog.object :as go])

adamvh20:06:00

then (defmacro my-macro [] (syntax-quote (go/symb ...)))

adamvh20:06:46

should work how you want as long you expand it in a cljs namespace where goog.object is aliased to go

dominicm20:06:18

@adamvh That approach seems a little magical & prone to unexpected errors. I probably won't take that approach, but thanks anyway.

adamvh20:06:37

yeah, i think it's probably best to write macros that aren't couple to, like, expected namespaces in which they should be evaluated

dominicm21:06:39

An interesting reason this may not work in some situations (it does for me, but that's an aside), is if you're requiring, e.g. cljsjs.react in your macro namespace. You must add it to a cljs namespace of some kind. That's not terrible, but it does create an implicit coupling.

mikeb23:06:53

Can anyone help with a regex & run-all-tests? I'm trying to build up a regex and pass to cljs.test/run-all-tests. Here's the code:

mikeb23:06:52

(let [rgx (re-pattern (str "example" ".*"))]
  (cljs.test/run-all-tests rgx))
=> clojure.lang.ExceptionInfo: clojure.lang.Symbol cannot be cast to java.util.regex.Pattern

mikeb23:06:53

So it looks like the run-all-tests macro isn't using the runtime value, but the symbol? Any suggestions to pass a dynamic regex to run-all-tests?

joelsanchez23:06:29

Looks like, since run-all-tests is a macro, it is taking rgx as a symbol instead of taking its value, I suggest solving this by using a macro yourself

joelsanchez23:06:46

(I tested your case locally and found the same problem)

joelsanchez23:06:18

For example doing the let in the macro and then taking the value of the regexp inside the syntax-quote

joelsanchez23:06:52

cljs.user=> (let [rgx (re-pattern (str "example" ".*"))] #_=> `(cljs.test/run-all-tests ~rgx)) (cljs.test/run-all-tests #"example.*")