Fork me on GitHub
#clojurescript
<
2018-09-17
>
Sal02:09:02

anyone have issues using drip lately?

Sal02:09:48

I’m getting this: error: Source option 1.5 is no longer supported. Use 1.6 or later

Sal02:09:05

make: * [classes/org/flatland/drip/Main.class] Error 2

gdanov09:09:25

anyone got advice how to handle numbers and floats input without going crazy in CLJS? the last in series of frustrations is

(number? ##NaN) ==> true
so I'm starting to suspect there's some logic in this madness that I'm missing

john13:09:32

Depends on what you want to accomplish. You can make a custom reader type #float that captures the float as a string, while read from a clj-side macro. Then have the float read into a type that calls .parseFloat when printed.

john13:09:04

Won't work in self hosted cljs though

john13:09:12

However, if you happen to know that the thing was a float type from the beginning, if the number gets coerced to an int, you can just add .0 to it when you print it.

gdanov16:09:19

I'm looking to parse <input> values E.g. transform strings into floats, that's all. ended up with my own fn but I'm pretty surprised clojurescript is not providing sane wrapper on top of the well-known js mess

john16:09:44

I think cljs would have to permanently box floats and any numbers they interact with, to prevent js from coercing things, which would be a pretty heavy weight solution, iiuc

john16:09:38

What are you doing with the data after parsing it? Doing math on it in js?

john16:09:48

Or spitting it out somewhere else?

roman01la10:09:45

(js/isNaN ##NaN) ;; true

roman01la10:09:38

or even (.isNaN js/Number ##NaN)

kwladyka10:09:09

What is the best way to test cljs modules with clj and deps.edn? I don’t need to run them in web browser. Should I use figwheel or use something simpler? What exactly? What choices I have when I need only run simple tests? My intuition says me fighweel-main is the best choice, but anyway I would like to ask what should I use to test opensource module for cljs.

awb9910:09:40

I am trying to display very simple tooltips on my page with clojurescript. I do not use react/reagent/etc. The only sample I found is https://github.com/oakmac/cljs-cheatsheet/blob/master/cljs-client/cljs_cheatsheet_client/tooltips.cljs but they do all the tooltip manipulation on their own. Any ideas? In pure javascript I would just get jquery and jquery ui, and it would be one function call really.

kwladyka10:09:53

Personally I would use reagent, exactly re-frame 🙂

kwladyka10:09:43

I know you wrote you don’t use it. But I would start to use it 🙂

awb9910:09:08

Is there a way to use re-frame without lots of boilerplate code?

kwladyka10:09:24

What boilerplate code do you mean?

kwladyka10:09:33

I don’t have such feeling about re-frame

awb9910:09:27

well, I am a begginer in clojurescript,

awb9910:09:37

so I figured I will do some server side rendering with hiccup and ring.

awb9910:09:48

And then add some jquery based stuff in the client.

awb9910:09:58

I had a look at several demos of re-frame,

awb9910:09:04

and they seemed all quite complex.

kwladyka10:09:19

Well the newest solution is https://github.com/bhauman/figwheel-main-template clj -A:new figwheel-main hello-world.app --reagent . But it is the newest solution, so there is not a lot of tutorials how to use cli. clj -A:new figwheel-main hello-world.app --reagent

kwladyka10:09:42

You can try it, but I warn you it will be hard on the beginning

kwladyka10:09:05

Not sure what experience you have, decide yourself 🙂

kwladyka10:09:24

There you have code ready to go

kwladyka10:09:54

but it this hard is not about re-frame, but about tooling around

awb9910:09:44

this is why I thought that I go with jquery solution first.

awb9910:09:49

as this is way easier.

kwladyka10:09:58

If you want to start from something simple and easy, start with lein and re-frame template. This boilerplate code is not about re-frame exactly. It can be a few lines to run it. It is more about architecture of app.

kwladyka10:09:50

But this hard things to learn are not about re-frame. It is more about tooling around clojurescript.

kwladyka10:09:20

Personally I wouldn’t use jquery with clojurescript

kwladyka10:09:52

because we have great tools like re-frame or fulcro

kwladyka10:09:14

which are newer and better

awb9910:09:20

can I use react components in re-frame ?

awb9910:09:28

I mean out of the box.

awb9910:09:35

there are tons of really good react libraries,

awb9910:09:42

that would be a motivation to use re-frame.

kwladyka10:09:10

yeah now we are talking about tooling around, because using npm dependencies in cljs is not easy, but it is what you can do.

kwladyka10:09:55

Choose one topic, figure out it and go to the next one. Small steps. Otherwise you can feel confuse.

kwladyka10:09:01

but it is really worth it

kwladyka10:09:43

I can recommend to start with https://github.com/bhauman/figwheel-main-template use lein or clj. Whatever is easier for you. Later you can easy change it.

kwladyka10:09:09

It is good solution. When you will learn how it works, then you can make next choices.

kwladyka10:09:51

But please consider I have years of experience with clj / cljs, so I can be not the best guy to recommend solutions for somebody who start with it now.

kwladyka10:09:57

I don’t remember how it was.

kwladyka11:09:12

I can only recommend tools which are my choice

bhauman11:09:03

goog.ui.Tooltip

bhauman11:09:38

@hoertlehner and I don’t seen any reason to start with re-frame or reagent unless you think you are going to have bunch of functionality

awb9911:09:57

that is my thinking too.

bhauman11:09:23

keeping it simple and understandable

awb9911:09:27

I got hiccup running client side,

bhauman11:09:32

That tooltip lib should do the trick

awb9911:09:34

and I want to render a nice popup window.

awb9911:09:45

It appears to me that google does only display a simple text.

awb9911:09:47

I was searching for examples for at least 4 hours now, and it appears to me that there are not many people who do old-style jquery apps with clojurescript,

awb9911:09:23

so perhaps it is the right thing to do to get started with re-frame, simply because this is what clojurescript community is focusing on.

bhauman11:09:03

@hoertlehner if you are looking for jQuery examples you are going to need to search for Javascript examples not ClojureScript examples

awb9911:09:50

I was hoping that I can skip figuring out how the js interop works till when I am more familiar with clojurescript.

awb9911:09:02

I thought that something as simple as popups,

awb9911:09:10

would be covered by a 101 clojurescript course.

awb9911:09:11

but not so.

bhauman11:09:42

yeah it sounds like you are wanting things to easier than they actually are 😉

awb9911:09:26

I am crazy 🙂

awb9911:09:42

My goal was to be up and running with a produciton style data mining app in 3 days.

bhauman11:09:48

like the rest of us

bhauman11:09:13

all while learning a new language

awb9911:09:28

yes of course.

bhauman11:09:30

and new tools

awb9911:09:34

when one jumps into the water,

awb9911:09:37

one has to jump.

awb9911:09:40

otherwise one never learns.

kwladyka11:09:56

heh but probably on the end you will use tools which I mentioned anyway. But maybe it will be good to realise why you want to use them 🙂

bhauman11:09:01

yeah that’s never my recommendation for learning ClojureScript

kwladyka11:09:35

Yeah, I don’t have too much experience about teaching.

bhauman11:09:37

I still think folks should start at half speed with ClojureScript

bhauman11:09:47

start super simple

bhauman11:09:04

people approach ClojureScript like learning ruby or python

bhauman11:09:14

or Javascript

bhauman11:09:39

there are more moving peices, and some subtle things going on

bhauman11:09:23

and Front end programming is not for the faint of heart either

bhauman11:09:30

especially today

kwladyka11:09:36

Probably everybody should find they own way. Everybody learning in different way. For example for me huge milestone for clj was this challanege https://github.com/kwladyka/chess-challenge . I was doing it about 3 months to really understand Clojure deeply.

kwladyka11:09:20

I was choosing hard things to understand things very deeply. But I was decided 100% I am going into Clojure.

bhauman11:09:22

those kinds of problems really really help

bhauman11:09:30

its only data

bhauman11:09:38

there is no interop

bhauman11:09:12

its just algorithms

kwladyka11:09:20

yes, but when you understand all puzzle around interop is not an issue then

bhauman11:09:35

so while you learn the algorithms you also are unconsciously learning the tooling environment

awb9911:09:11

bruce: In case you ever want to move your cubicle to a warm climate: I bought a little lake in mexico, if you want to hang out there for some time, you can stay there for free. http://www.ranchokalan.com

bhauman11:09:20

oh so you bought a lot there?

kwladyka11:09:26

To figure out this way I had to try 100 other things to find right one

awb9911:09:37

yes, I bought 2 lakes.

awb9911:09:44

100 hectar.

awb9911:09:49

nobody there.

awb9911:09:59

no electricity, but sun is plenty, so with solar you are good to go.

kwladyka11:09:13

Which country?

awb9911:09:17

lake is drinking water quality.

awb9911:09:24

near playa del carmen.

kwladyka11:09:39

oh too far for me, but sounds super cool

kwladyka11:09:30

I really love nature

bhauman11:09:05

@hoertlehner I could build a Dome there!

awb9911:09:17

yes, this is what I meant.

awb9911:09:28

I just confused dome with cubicle.

awb9911:09:13

nature is really nice there.

kwladyka11:09:44

Damn why most of clj people are from US

awb9911:09:49

I guess you would need to adapt the dome a little bit,

awb9911:09:56

because climate is hotter.

bhauman11:09:01

well I build other things

bhauman11:09:18

and material sourcing is different there

awb9911:09:56

definitely.

awb9911:09:56

but also easy to get certain things from us.

bhauman11:09:12

is it all friends who have bought in?

awb9911:09:49

So far it is just me and 2 friends.

awb9911:09:02

We saw the lake,

awb9911:09:03

liked it.

awb9911:09:11

and then started buying one lot after the next.

awb9911:09:14

it just happened.

awb9911:09:28

for mexicans a lake has no value

awb9911:09:32

as most of them cannot swim.

bhauman12:09:11

do you own the whole thing?

awb9912:09:22

I own 100 hectar

awb9912:09:26

together with 2 friends.

awb9912:09:32

1 hectar = 10000 squarmeter.

awb9912:09:38

so we do have space.

bhauman12:09:06

well that’s fun

awb9912:09:04

took us almost 3 years to get permissions though.

awb9912:09:05

but ok...

pesterhazy13:09:02

https://dev.clojure.org/jira/browse/CLJS-2376 mentions a way to refer to JS global exports like this:

(:require ["material-ui/RaisedButton" :refer (default) :rename {default RaisedButton}])

pesterhazy13:09:28

But when I try it like this

(:require [react-select :refer (default)])
default ends up as nil

thheller13:09:12

@pesterhazy it might be getting renamed to .default$. it handled a bit weirdly in CLJS currently.

pesterhazy13:09:27

ah because default is a keyword is ES6?

thheller13:09:05

try setting :language-out :ecmascript5. I believe thats the setting that controls that.

thheller13:09:43

hmm it might just not be working with the global exports feature at all

pesterhazy13:09:37

looking at the compiler output it compiles down to

cljs_spa.page.home.global$module$react_select.default$

thheller13:09:01

yeah looks like a bug to me

roman01la13:09:47

I think I’ve reported this issue 1 or 2 years ago, not sure if it was fixed though

pesterhazy13:09:02

@thheller you were right - it works when you set

:language-out :ecmascript5

roman01la13:09:39

oh, nice 👌

thheller13:09:51

oh so it did work. interesting.

pesterhazy13:09:07

I wonder if this is safe:

(:require [react-select :refer [default] :rename {default react-select}])

pesterhazy13:09:41

I'm worried about using react-select twice, first as the name of the module, and then as the rename target

thheller13:09:18

shouldn't be a problem

pesterhazy13:09:39

the compiled output looks fine:

cljs_spa.page.home.global$module$react_select = goog.global["react-select"];

// usage
console.log(cljs_spa.page.home.global$module$react_select.default);

awb9913:09:25

does the http://goog.net Jsonp need any special require in project.clj ?

awb9913:09:44

I am getting this error when I want to use it.

pesterhazy14:09:35

@hoertlehner

cljs.user=> (require '[goog.net.Jsonp])
nil
cljs.user=> (goog.net.Jsonp.)
#object[Object [object Object]]

awb9914:09:59

so import is the old syntax?

pesterhazy14:09:22

I think you need the require in any case

pesterhazy14:09:01

additionally import gives you a shortcut

cljs.user=> (import '[ Jsonp])
nil
cljs.user=> (Jsonp.)
#object[Object [object Object]]

awb9914:09:53

So should I remove the ns / :import athat I have?

pesterhazy14:09:37

if you're using the fully qualified symbol, you don't need the import stanza AFAIK

awb9914:09:56

Unfortunately this is also not working 😞

awb9914:09:04

same error.

awb9914:09:16

TypeError: goog.net.jsloader.load is not a function

awb9914:09:25

figwheel is also complaining about this.

awb9914:09:13

I basically tried to run all kind of examples that I found,

awb9914:09:16

and none of them works.

pesterhazy14:09:48

you may need to require goog.net.jsloader as well

pesterhazy14:09:11

what do you need Jsonp for btw? Don't people just use js/fetch these days?

awb9914:09:27

I dont know; I am trying to understand goog and core.async http://swannodette.github.io/2013/11/07/clojurescript-101

kwladyka14:09:31

npm deps and webpack

import deepPurple from "@material-ui/core/colors/deepPurple";
import green from "@material-ui/core/colors/green";
import blue from "@material-ui/core/colors/blue";
window.MaterialUiColors = {
    deepPurple: deepPurple,
    green: green,
    blue: blue
}
Can I modify it to something like this:
window.MaterialUiColors = {
    deepPurple: import deepPurple from "@material-ui/core/colors/deepPurple",
    green: import green from "@material-ui/core/colors/green",
    blue: import blue from "@material-ui/core/colors/blue"
}
I would like to not repeat this lines and instead assign import to the right place in one line. how?

justinlee15:09:51

@kwladyka you cannot do that with import like you could have done with require. import is inherently static

kwladyka15:09:57

Can I use require here instead?

kwladyka15:09:20

webpack will be fine with it?

kwladyka15:09:32

no cons about size of files or whatever?

justinlee15:09:34

no concerns about file size, but you’ll have to figure out how to deal with default imports. i think you do something like require("@material-ui/core/colors/green").default or something like that. the default import syntax is the only thing that is really different with import statements

thheller16:09:59

with webpack this can actually affect the file size since their tree-shaking only works with import

thheller16:09:30

its fine for the colors though since there is nothing to shake

kwladyka16:09:02

hmm so conclusion is I have to use import to not affect size of js. Am I right?

thheller16:09:09

it mostly depends on which libraries you use. require is mostly fine since you are probably not going to actually only import what you need

thheller16:09:37

ie. import {a,b,c} from "something" vs import * as x from "something"

kwladyka16:09:22

oh will it be ok only with default export?

kwladyka16:09:36

but not with import {a,b,c} from "something"

kwladyka16:09:08

that is what you mean by > their tree-shaking only works with import

thheller16:09:27

require is basically import * as x from "something". so everything in "something" will end up in your build

thheller16:09:05

with import {a,b,c} from "something" webpack can remove whatever else is defined besides a,b,c

kwladyka09:09:16

window.React = require("react");
window.ReactDOM = require("react-dom");

// material-ui

window.MaterialUiStyles = {
    createMuiTheme: require("@material-ui/core/styles").createMuiTheme,
    MuiThemeProvider: require("@material-ui/core/styles").MuiThemeProvider
}

window.MaterialUiCore = {
    Grid: require("@material-ui/core/Grid").default,
    Paper: require("@material-ui/core/Paper").default,
    AppBar: require("@material-ui/core/AppBar").default,
    Toolbar: require("@material-ui/core/Toolbar").default,
    Typography: require("@material-ui/core/Typography").default,
    IconButton: require("@material-ui/core/IconButton").default,
    Button: require("@material-ui/core/Button").default,
    Drawer: require("@material-ui/core/Drawer").default,
    TextField: require("@material-ui/core/TextField").default
}

window.MaterialUiColors = {
    deepPurple: require("@material-ui/core/colors/deepPurple").default,
    green: require("@material-ui/core/colors/green").default,
    blue: require("@material-ui/core/colors/blue").default
}

window.MaterialUiIcons = {
    Menu: require("@material-ui/icons/Menu").default,
    AccountCircle: require("@material-ui/icons/AccountCircle").default,
    Terrain: require("@material-ui/icons/Terrain").default
}

kwladyka09:09:38

What do you think about it? Especially about createMuiTheme: require("@material-ui/core/styles").createMuiTheme, ?

kwladyka09:09:14

Is it as good as import {createMuiTheme, MuiThemeProvider} from "@material-ui/core/styles"?

thheller09:09:19

I think it horrible and would use shadow-cljs 😉

thheller09:09:27

no it is not

kwladyka09:09:42

hah I like your honest 🙂

thheller09:09:49

tree shaking only works with import

thheller09:09:36

but honestly you'll have to test this for yourself. I don't follow the webpack development that closely

kwladyka09:09:17

It looks horrible, but it is not so bad. Because now I can require [material-ui-core :as mui-core] instead of dozens of files. It is a little like a choice between require them in cljs or in webpack. This lines have to be written anyway.

kwladyka09:09:15

to be fair 🙂

kwladyka09:09:53

BTW fighweel-main has {:npm {:bundles {"dist/index_bundle.js" "src/js/index.js"}}} which mean developers have to care only about js import / require stuff in index.js. Do not have to update :foreign-libs and :provides. Just saying to share what I have learned about tooling around node deps.

kwladyka09:09:21

But for sure shadow-cljs rules. It is super great tool.

jerome16:09:27

What are you all using in terms of ClojureScript libraries/frameworks for complex single page apps? We've got a react/redux JS app that we're considering moving over to ClojureScript, and although I've got ideas about what to use for a prototype, I'm leery of making any decisions in a vacuum.

lilactown16:09:55

a lot of people use reagent and re-frame. it is pretty much the react/redux of CLJS

4
jerome16:09:00

I suspected as much. Are there other, entirely different paradigms you'd recommend?

lilactown16:09:46

there are some other, slightly more niche but more opinionated frameworks built on top of reagent like keechma

lilactown16:09:29

fulcro is another framework built on top of React, outside of reagent

lilactown16:09:37

if you're interested in exploring things that are completely different than the React paradigm, hoplon + javelin is quite interesting

jerome16:09:27

Thanks. I just want to make sure I don't pigeonhole us into a react/redux mindset when there might be better abstractions in the ClojureScript world.

awb9916:09:51

I am trying to make http requests from within clojurescript, and I have some kind of dependency issue.

awb9916:09:52

#object[ReferenceError ReferenceError: cljs_http is not defined]

awb9916:09:09

I am using figwheel.

awb9916:09:30

Is there a way how I can see which dependencies are loaded in clojurescript?

lilactown16:09:35

@hoertlehner are you using lein or cli tools or?

pesterhazy16:09:04

@hoertlehner here's a simple way to make a GET request that doesn't require any deps:

(-> (js/fetch "") (.then (fn [r] (.json r))) (.then (fn [r] (js/console.log r))))

pesterhazy16:09:52

works in any modern browser, or node with fetch replaced with a reference to the node-fetch modules

awb9916:09:04

your sample prints <undefined>

awb9916:09:12

I guess it should print something else.

lilactown16:09:15

you can run lein deps :tree to see what your full dependency graph is

lilactown16:09:09

if you're trying to use cljs-http, you'll need to add it to your leiningen dependency list in project.clj

awb9916:09:41

@pesterhazy Your example still prints <unavailable>

pesterhazy16:09:46

unavailable?

pesterhazy16:09:54

Hard to say what you're doing wrong with so little information, but this should work

mfikes16:09:44

@hoertlehner If you want to see which namespaces are currently loaded in the REPL, you can make a file src/utils/core.clj with a macro:

(ns utils.core)

(defmacro loaded-namespaces []
  `'~(sort (keys (:cljs.analyzer/namespaces @cljs.env/*compiler*))))
and then put this in src/user.cljs:
(require-macros '[utils.core :refer [loaded-namespaces]])
With that, (loaded-namespaces) will return a list of the loaded namespaces.

pesterhazy16:09:09

that's pretty cool ^^

awb9916:09:35

#object[TypeError TypeError: cljs.env is undefined] [email protected]://localhost:3449/js/compiled/out/figwheel/client/utils.js line 174 > eval:3:263 @http://localhost:3449/js/compiled/out/figwheel/client/utils.js line 174 > eval:1:313 @http://localhost:3449/js/compiled/out/figwheel/client/utils.js line 174 > eval:1:276 @http://localhost:3449/js/compiled/out/figwheel/client/utils.js line 174 > eval:1:2 [email protected]://localhost:3449/js/compiled/out/figwheel/client/utils.js:174:8

mfikes16:09:25

Hmm. Maybe cljs.env is not automatically loaded for you. To make that utils.core namespace be correct, you could throw in a (:require cljs.env), but that makes me wonder if something else is wrong (It is hard to have a working REPL without that being loaded.)

awb9916:09:11

it is bizarre.

awb9916:09:18

even the required did not help

mfikes16:09:48

Interesting. Ignoring the user.cljs auto-loaded namespace, you should be able to require that macro from the REPL:

(require-macros '[utils.core :refer [loaded-namespaces]])

awb9917:09:44

fuck. it is not working.

mfikes17:09:36

Really? This is just a simple macro that accesses some compiler internals 🙂 Is it in utils/core.clj file?

awb9917:09:44

yes in core.

awb9917:09:57

I think I need to remove my clojure isntallation

awb9917:09:01

and start from scratch somehow.

awb9917:09:19

I guess I did not upgrade correctly to clojure 1.9

awb9917:09:43

thanks mdikes!!

mfikes17:09:29

Interesting. I have no ideas regarding what could be broken.

john16:09:03

Is there anything about using that macro in a lib that would break for downstream consumers?

john16:09:47

aka, might that be considered "ambient env"

thheller16:09:14

the macro isn't completely accurate. only because the analyzer data is present does not mean that the JS runtime has loaded the code

thheller16:09:32

ie. (require 'some.thing) then reload the browser

mfikes16:09:42

Well, it's impure, so if you have a lib that dumps that into a def that is in your compiled JavaScript that would be a problem. But the intent is just to show things in the REPL.

thheller16:09:42

analyzer will have the data but the client won't (just fixed a related bug in shadow-cljs ;)

mfikes16:09:23

You'd have to go fishing in the runtime to see what is loaded in JavaScript

dpsutton16:09:02

i've got a cljc file with a -main which calls some benchmarks with criterium or in cljs they use simple-benchmark. I can easily run this with clojure with clj -A:bench -m ns and it runs the benchmark main function. How can i achieve this with clojurescript since i need to declare main as cljs.main. Is the best i can do clj -A:bench cljs.main -e "(require ns) (ns/-main)"?

john16:09:27

cljs.main takes a --main/-m ns

dpsutton16:09:29

worked a charm. thanks @john

mfikes17:09:42

Here is a better macro that I think addresses the good point that @thheller raised

(defmacro loaded-namespaces []
  `(remove nil? [[email protected](map (fn [ns] `(when (cljs.core/exists? ~ns) '~ns))
       (sort (keys (:cljs.analyzer/namespaces @cljs.env/*compiler*))))]))

awb9917:09:53

The most basic request works in chromium, but not in firefox.

awb9917:09:59

is this bizzarre or what?

awb9917:09:45

And even stranger a direct url request in the browser does work.

john17:09:09

strange, works for me with figwheel in both chrome and firefox

awb9917:09:45

Installing CLJS DevTools 0.9.0 and enabling features :formatters :hints :async util.cljs:176:55 Feature :formatters cannot be installed. Unsupported Javascript context: Mozilla/5.0 (X11; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0. util.cljs:237:13 CLJS DevTools: some custom formatters were not rendered. https://github.com/binaryage/cljs-devtools/blob/master/docs/faq.md#why-some-custom-formatters-were-not-rendered

awb9917:09:54

This is what it tells me on firefox.

awb9917:09:03

just warnings,

awb9917:09:05

but perhaps related.

john17:09:32

Yeah, I've got that too. I don't think that should matter

justinlee17:09:08

does it work if you just try the request directly in the js console? i.e. fetch("").then(r => r.json()).then(console.log);

john17:09:23

Check if any plugins are doing fancy business too

john17:09:32

noscript, etc

awb9917:09:19

I just restarted firefox,

awb9917:09:21

now all works.

awb9917:09:24

how bizarre.

awb9917:09:48

I have tried for sure 200 times today.

awb9917:09:31

perhaps I had connected figweel too many times,

awb9917:09:38

and at some time it blew something up.

john17:09:33

using any js deps that polyfill fetch on ff? I've never seen figwheel cause that.

awb9918:09:13

no nothing.

awb9918:09:19

stupid question..

awb9918:09:31

how do I convert the js object back to a clojure script object?

awb9918:09:51

this then does not use keywords,

awb9918:09:54

but uses strings in the map.

john18:09:33

(js->clj json-str :keywordize-keys true)

john18:09:33

But be mindful that if the purpose of your function is to then immediately convert that back into js to be consumed by some js thing, doing the conversion back and forth could be less performant than just doing the thing on the js obj

awb9918:09:42

this cool trick I couldnt find in the books I read.

john18:09:23

But, if you're taking that data and then storing it in an atom somewhere, to be operated on in some later context, then sure, you might as well convert it.

awb9918:09:05

I am just doing a prototype.

awb9918:09:09

so no performance issues.

awb9918:09:20

But using the js in clojurescript is horrible.

awb9918:09:29

Just pure js with async await,

john18:09:29

agreed 🙂

awb9918:09:32

is much nicer.

awb9918:09:51

In pure JS I use ramda,

awb9918:09:04

and this allows me to do a query like that really simple and nice.

john18:09:18

async/await is panning out pretty nicely for js. I much prefer reading js written with async/await

awb9918:09:33

I had the naive assumption that clojurescript is would have an even better syntax.

john18:09:07

After async/await idioms settle in the js world, I wouldn't be surprised if the CLJS world decides to bring in a native version. One problem is that async/await introduces a whole new function type to js. So integrating that with CLJ/Ss single function type would have to be done gingerly, if at all possible.

awb9918:09:19

but the repl driven development is way better in clojurescript.

john18:09:49

There's an async/await polyfill built on promises, so it could probably be made as a lib cljs now. One issue is that the CLJS crowd isn't yet fully sold on the method. So that's probably why no one has cared to build a lib for that yet.

awb9918:09:00

even though javascript would have everything ready for repl driven evelopment,

john18:09:04

Well, actually, somebody pretty much did build one

awb9918:09:06

I havent managed to do so.

john18:09:25

So, if you really want the slick syntax, you can have it

awb9918:09:44

I have to study that!

justinlee19:09:26

If you take a look at the clojureverse thread linked to in that library, the point that I and other tried to make is that native async/await is about more than just syntax: its about better stack traces, better tooling, and using the much more solid and bug free implementations provided by the larger js communities.

justinlee19:09:49

There’s a reason why js people stayed away from it until it was available natively: the polyfill involves the same state-machine transformation that the go macro uses, which is very hard to debug when things go wrong.

justinlee19:09:20

The other point I tried to make is that this isn’t a “trendy” javascriptism--it wasn’t even invented by javascript and it has been ported to many major languages now.

awb9919:09:15

@U8ES68TGX I still have problems sometimes with exceptions in async / await. Even with bluebird and all logging on, there are still some instances where it goes very wrong. This is my main issue I haave with async / await pipelines.

john19:09:12

@U8ES68TGX I'd love to see a full proposal on what bringing async/await into cljs proper would look like

john19:09:33

While preserving cljs's function semantics

justinlee20:09:47

@john yea i don’t know what else beyond shaun’s proposal would be needed. i’m not familiar with cljs internals

justinlee20:09:55

the only implementation issue anybody raised is the way the compiler creates lexical scopes, but shaun identified the way to change code generation and which forms would need to change

justinlee20:09:07

@hoertlehner i imagine that is so, but try your hand at core.async for a while and you’ll soon appreciate how sophisticated js async tools are

john20:09:11

@U8ES68TGX ah, I didn't see that one before. Nice

john20:09:47

hmm, seems to me, this proposal would make a lot of cljs code a lot less portable to clj

john20:09:09

If that proposal could be converted to use clojure's promise semantics, where you await something by derefing it, that might be more portable.

john20:09:18

OTOH, we wouldn't want the semantics to be too divergent either. The same blocking and synchronization semantics should hold between both languages, at least when in a single threaded mode.

john20:09:21

Otherwise you've got greater divergence between languages for how state is transformed

john20:09:43

My preferred solution is to bring "proper" blocking semantics to cljs using webworkers as threads, so we can preserve clojure semantics proper

justinlee20:09:45

i’m one of those weird people that actually likes async programming and would like to see cljs embrace it

john20:09:51

But there's other proposals in the JS world that could bring in proper multi-threading anyway. So CLJS could just wait for that later standard and then just port clojure's proper parallelism semantics over that.

justinlee20:09:19

well for people like me that are actually building profit-oriented businesses on cljs right now, this exercise is not academic

justinlee20:09:54

but i don’t have time to do it myself so i can’t really complain

john20:09:59

I make money on cljs too. But I came from clojure, not js.

john20:09:37

So perhaps I'm more biased on preserving cljs's clojureyness

justinlee20:09:47

right and i think you’re in the majority. cljs is (largely) a tool for java programmers who don’t really like or appreciate javascript

john20:09:11

That's true to an extent

john20:09:17

But you've got to really appreciate what clojure does for the java world, to appreciate why we want to preserve those idioms in js. Some of them don't appear to pay off at the moment, but I assure you, once multi-threading in js becomes a more common thing, CLJS will be your secret weapon.

justinlee20:09:00

well it’ll be 5 years at least so i won’t hold my breath 🙂

john20:09:36

eh, I'd give it 2 years

john20:09:12

With SharedArrayBuffers, js devs can can start mucking around in mutable, shared state parallelism right now

justinlee20:09:28

2 years until we have sufficient browser adoption to build a business on it? i’d be surprised but maybe i’ll be wrong

john20:09:45

All the tech is already adopted. It'll just be 2 years before js lib authors provide parallel idioms to exploit the tech that is available.

john20:09:06

All the browsers now have SABs

awb9922:09:16

frontend development needs to be massively simplified.

awb9922:09:40

You can hack some 15 year old winforms app together really fast,

awb9922:09:53

and web frontend takes 2x or 5x the amoutn of work.

awb9922:09:59

sure, there are some additional problems,

awb9922:09:05

but they are mostly the same,

leocardoso19:09:20

how I can access the property in a js object like that?

{0: "123"}

mfikes19:09:31

If you don't need :advanced renaming (goog.object/get #js {"0" "123"} "0")

jaawerth19:09:59

yeah, you'll need to use goog.object/get there - keep in mind that JS objects coerce numerical keys to strings

mfikes19:09:06

Oh, wait, that's a number

jaawerth19:09:23

your example will still work, since it's not really a number

mfikes19:09:50

Yeah, I don't know JS 🙂

jaawerth19:09:23

that one is JS's fault, really. The new Map object can have everything as a key, objects have to rely on lies and deceit 😄

mfikes19:09:57

I'm not blaming JS. The problem lies with me. 🙂

jaawerth19:09:48

goog.object/get should be able to take either 0 or "0" in that example, I think

jaawerth19:09:51

funnily, it's not documented as such, but aget also works. probably because the lookup is the same

jaawerth19:09:03

not that I'm recommending people do that without it being documented to work

mfikes19:09:05

FWIW, goog.object/get documents its key argument as being string type

richiardiandrea19:09:30

Hello folks! I have this open source cljs script - when I do time bin/terraform-env-vars I see real 0m0.241s...It's compiled to JS so I did not expect such a high bootstrapping time - compiler options are:

{:optimizations :simple}

richiardiandrea19:09:51

how do I even start profiling node 😄

mfikes19:09:08

Hrm. On the surface that does seem slow for Node

jaawerth19:09:43

@mfikes makes sense - it expects a string, it's just that there's coercion involved and it just happens not to screw things up for numbers. Like, if you tried to use an object as the key there it would probably try to look up a property at obj["[object Object]"]

mfikes19:09:51

JS ¯\(ツ)

jaawerth19:09:21

coercing all the things since 1990-ish

jaawerth19:09:26

haha yeah, (goog.object/get #js{ "[object Object]" "foo" } #js{:a 1 :b 2}) yields "foo"

mfikes19:09:28

@richiardiandrea FWIW, for the Quick Start "Hello world" printing program, I get 0.274 s, but if I add -O simple it drops to 0.150 s and with -O advanced I get 0.092 s

jaawerth19:09:07

@richiardiandrea as for profiling you can launch node with an --inspect or --inspect-brk among other things that lets you connect to it via chrome's dev tools, and use the profiler there. May have to finagle it to profile the initialization bits, though. The node docs has a guide for debugging that goes into details

👍 4
richiardiandrea19:09:08

I remember David was saying that I never ever need to use :advanced...

richiardiandrea19:09:46

so yeah with :advance I see real 0m0.152s and it feels faster

richiardiandrea19:09:21

so not as low, but still worth having it

mfikes19:09:22

The difference between :simple and :advanced can be an order of magnitude less JavaScript to parse.

richiardiandrea19:09:03

yeah so I didn't really understand the point of not needing :advanced in node scripts all all before 😄

jaawerth19:09:41

maybe they meant apps? where you don't care as much about initial boot time? or because it's still way faster than java would be to start?

mfikes19:09:55

I would suggest that :advanced is still deemed critical for web apps, but falls into the area of "nice to have" for Node

richiardiandrea19:09:56

yeah maybe he was actually talking about lambda

mfikes19:09:32

Yeah, I think @jesse.wertheim is right. If you have a long-lived Node app, then optimizations have a chance to kick in.

mfikes19:09:40

But for a script...

richiardiandrea19:09:59

yeah, there is still the lambda cold startup problem but yeah, that's another kettle of fish 😄

richiardiandrea19:09:10

thanks a lot folks, I will go with :advanced