This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-17
Channels
- # 100-days-of-code (4)
- # announcements (4)
- # aws (2)
- # beginners (88)
- # cider (1)
- # cljsrn (9)
- # clojure (126)
- # clojure-conj (4)
- # clojure-dev (8)
- # clojure-greece (1)
- # clojure-italy (37)
- # clojure-nl (3)
- # clojure-spec (13)
- # clojure-uk (91)
- # clojurescript (392)
- # clojurewerkz (1)
- # clojutre (10)
- # core-async (6)
- # cursive (5)
- # data-science (1)
- # datomic (41)
- # emacs (21)
- # events (1)
- # figwheel-main (52)
- # fulcro (2)
- # hyperfiddle (4)
- # jobs (3)
- # jobs-discuss (9)
- # luminus (3)
- # lumo (9)
- # mount (1)
- # nyc (1)
- # off-topic (73)
- # other-languages (6)
- # pedestal (8)
- # portkey (2)
- # re-frame (9)
- # reagent (8)
- # rum (17)
- # shadow-cljs (38)
- # sql (19)
- # tools-deps (18)
- # yada (4)
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 missingDepends 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.
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.
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
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
(js/isNaN ##NaN) ;; true
or even (.isNaN js/Number ##NaN)
the second one is more robust according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
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.
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.
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
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.
But this hard things to learn are not about re-frame
. It is more about tooling around clojurescript.
yeah now we are talking about tooling around, because using npm
dependencies in cljs is not easy, but it is what you can do.
Choose one topic, figure out it and go to the next one. Small steps. Otherwise you can feel confuse.
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.
It is good solution. When you will learn how it works, then you can make next choices.
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.
@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
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,
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.
@hoertlehner if you are looking for jQuery examples you are going to need to search for Javascript examples not ClojureScript examples
I was hoping that I can skip figuring out how the js interop works till when I am more familiar with clojurescript.
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 🙂
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.
I was choosing hard things to understand things very deeply. But I was decided 100% I am going into Clojure.
so while you learn the algorithms you also are unconsciously learning the tooling environment
much more http://clojure.wladyka.eu/posts-output/2015-08-24-how-to-improve-algorithm-speed.html
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
@hoertlehner I could build a Dome there!
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}])
But when I try it like this
(:require [react-select :refer (default)])
default
ends up as nil@pesterhazy it might be getting renamed to .default$
. it handled a bit weirdly in CLJS currently.
ah because default
is a keyword is ES6?
try setting :language-out :ecmascript5
. I believe thats the setting that controls that.
@thheller here's the full code: https://github.com/pesterhazy/cljs-spa-example/pull/14/files
In the example, react-select
is defined as a global export: https://github.com/pesterhazy/cljs-spa-example/blob/009d1e495cb398586582f4c43a3186c1f432d04d/dev.cljs.edn#L10
https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/compiler.cljc#L458-L483
looking at the compiler output it compiles down to
cljs_spa.page.home.global$module$react_select.default$
I think I’ve reported this issue 1 or 2 years ago, not sure if it was fixed though
@thheller you were right - it works when you set
:language-out :ecmascript5
oh, nice 👌
I wonder if this is safe:
(:require [react-select :refer [default] :rename {default react-select}])
I'm worried about using react-select
twice, first as the name of the module, and then as the rename target
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);
does the http://goog.net Jsonp need any special require in project.clj ?
cljs.user=> (require '[goog.net.Jsonp])
nil
cljs.user=> (goog.net.Jsonp.)
#object[Object [object Object]]
I think you need the require in any case
additionally import gives you a shortcut
cljs.user=> (import '[ Jsonp])
nil
cljs.user=> (Jsonp.)
#object[Object [object Object]]
this post may or may not explain it: https://www.martinklepsch.org/posts/requiring-closure-namespaces.html
if you're using the fully qualified symbol, you don't need the import stanza AFAIK
you may need to require goog.net.jsloader
as well
what do you need Jsonp for btw? Don't people just use js/fetch
these days?
I dont know; I am trying to understand goog and core.async http://swannodette.github.io/2013/11/07/clojurescript-101
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?@kwladyka you cannot do that with import
like you could have done with require
. import is inherently static
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
with webpack this can actually affect the file size since their tree-shaking only works with import
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
require
is basically import * as x from "something"
. so everything in "something"
will end up in your build
with import {a,b,c} from "something"
webpack
can remove whatever else is defined besides a,b,c
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
}
What do you think about it? Especially about createMuiTheme: require("@material-ui/core/styles").createMuiTheme,
?
Is it as good as import {createMuiTheme, MuiThemeProvider} from "@material-ui/core/styles"
?
but honestly you'll have to test this for yourself. I don't follow the webpack development that closely
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.
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.
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.
a lot of people use reagent and re-frame. it is pretty much the react/redux of CLJS
there are some other, slightly more niche but more opinionated frameworks built on top of reagent like keechma
if you're interested in exploring things that are completely different than the React paradigm, hoplon + javelin is quite interesting
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.
I am trying to make http requests from within clojurescript, and I have some kind of dependency issue.
@hoertlehner are you using lein or cli tools or?
@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))))
works in any modern browser, or node with fetch replaced with a reference to the node-fetch modules
if you're trying to use cljs-http, you'll need to add it to your leiningen dependency list in project.clj
fixed the example @hoertlehner
more complete example here https://github.com/pesterhazy/cljs-spa-example/blob/1c72a3e7a5915a5d8d665cce81b09850bf52a2b7/src/cljs_spa/page/profile.cljs#L7
@pesterhazy Your example still prints <unavailable>
unavailable?
Hard to say what you're doing wrong with so little information, but this should work
@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.that's pretty cool ^^
#object[TypeError TypeError: cljs.env is undefined] utils$core$loaded_namespaces@http://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 figwheel$client$utils$eval_helper@http://localhost:3449/js/compiled/out/figwheel/client/utils.js:174:8
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.)
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]])
Really? This is just a simple macro that accesses some compiler internals 🙂
Is it in utils/core.clj
file?
Here it is working in figwheel-main: https://gist.github.com/mfikes/fffbdb4aafe221b21cc0a9856923e7d9
Is there anything about using that macro in a lib that would break for downstream consumers?
the macro isn't completely accurate. only because the analyzer data is present does not mean that the JS runtime has loaded the code
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.
analyzer will have the data but the client won't (just fixed a related bug in shadow-cljs ;)
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)"
?
Here is a better macro that I think addresses the good point that @thheller raised
(defmacro loaded-namespaces []
`(remove nil? [~@(map (fn [ns] `(when (cljs.core/exists? ~ns) '~ns))
(sort (keys (:cljs.analyzer/namespaces @cljs.env/*compiler*))))]))
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
does it work if you just try the request directly in the js console? i.e. fetch("
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
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.
async/await is panning out pretty nicely for js. I much prefer reading js written with async/await
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.
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.
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.
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.
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.
@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.
@U8ES68TGX I'd love to see a full proposal on what bringing async/await into cljs proper would look like
@john yea i don’t know what else beyond shaun’s proposal would be needed. i’m not familiar with cljs internals
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
@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
@U8ES68TGX ah, I didn't see that one before. Nice
hmm, seems to me, this proposal would make a lot of cljs code a lot less portable to clj
If that proposal could be converted to use clojure's promise semantics, where you await something by derefing it, that might be more portable.
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.
My preferred solution is to bring "proper" blocking semantics to cljs using webworkers as threads, so we can preserve clojure semantics proper
i’m one of those weird people that actually likes async programming and would like to see cljs embrace it
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.
well for people like me that are actually building profit-oriented businesses on cljs right now, this exercise is not academic
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
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.
this is out there now https://github.com/mbasso/wasm-worker
With SharedArrayBuffers, js devs can can start mucking around in mutable, shared state parallelism right now
2 years until we have sufficient browser adoption to build a business on it? i’d be surprised but maybe i’ll be wrong
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.
how I can access the property in a js object like that?
{0: "123"}
yeah, you'll need to use goog.object/get
there - keep in mind that JS objects coerce numerical keys to strings
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 😄
funnily, it's not documented as such, but aget
also works. probably because the lookup is the same
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}
how do I even start profiling node
😄
@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]"]
haha yeah, (goog.object/get #js{ "[object Object]" "foo" } #js{:a 1 :b 2})
yields "foo"
@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
oh wow
@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
I remember David was saying that I never ever need to use :advanced
...
let me try that
so yeah with :advance
I see real 0m0.152s
and it feels faster
so not as low, but still worth having it
The difference between :simple
and :advanced
can be an order of magnitude less JavaScript to parse.
yeah so I didn't really understand the point of not needing :advanced
in node
scripts all all before 😄
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?
I would suggest that :advanced
is still deemed critical for web apps, but falls into the area of "nice to have" for Node
yeah maybe he was actually talking about lambda
Yeah, I think @jesse.wertheim is right. If you have a long-lived Node app, then optimizations have a chance to kick in.
yeah, there is still the lambda
cold startup problem but yeah, that's another kettle of fish 😄
thanks a lot folks, I will go with :advanced