Fork me on GitHub
#clojurescript
<
2015-07-14
>
lucien.knechtli03:07:20

wow - and I thought that clojure build errors could be indecipherable: https://www.refheap.com/106544 anyone got a clue what could cause this?

lucien.knechtli03:07:23

Using clojurescript 0.0-3308 and clojure 1.7.0

lucien.knechtli03:07:03

or should I be asking this stuff in a different channel

joshg03:07:51

I’d like to use an external React component in a ClojureScript project. It’s an ES6 module that’s been transpiled to UMD. Can anyone offer suggestions on how to generate externs? This is the component: https://github.com/orgsync/react-list/

joshg03:07:37

@lucien.knechtli: are you requiring korma.core in a cljs file?

lucien.knechtli03:07:04

No, I use it on the server

lucien.knechtli03:07:56

The cljs file is basically torn from the default reagent lein template, except I replaced secretary with bidi

lucien.knechtli03:07:38

Oh.. If that's the case, is there any way to resolve it other than getting rid of cider-nrepl?

lucien.knechtli03:07:42

Disregard that, I'll try what is recommended in the thread

lucien.knechtli03:07:29

yay! i'm getting errors that make sense now!

mikethompson08:07:55

@dkvasnicka: re-frame and zelkova are your two obvious options. Hoplon (not reagent) is also FRP.

casperc13:07:30

What is the correct way of using the google clojure stuff? I am trying to go through the Secretary stuff but am coming against this error: WARNING: Use of undeclared Var xyz.routes/History at line 7 xyz/routes.cljs

casperc13:07:56

I am trying to do something like this: (defn hook-browser-navigation! [] (doto (History.) (events/listen EventType/NAVIGATE (fn [event] (secretary/dispatch! (.-token event)))) (.setEnabled true)))

casperc13:07:27

Basically it is the history stuff that messes up

robert-stuttaford13:07:12

do you have (:import [goog.history History]) ?

casperc13:07:17

I have tried a number of different variations, I have (:import [goog.history]) which doesn't complain when loading the namespace form

casperc13:07:39

your version doesn't work though, as far as I can tell

casperc13:07:37

So this is basically what my ns looks like (ns sagsbehandler.routes (:require [secretary.core :as secretary :refer-macros [defroute]] [goog.events :as events] [goog.history.EventType :as EventType]) (:import [goog.history])) (History.)

casperc13:07:14

And I get an error with ExceptionInfo #<TypeError: undefined is not a function> clojure.core/ex-info (core.clj:4403)

shofetim13:07:55

nvm, looks like you did simple_smile

casperc13:07:17

Yeah, so the thing is that I think that might be a bit out of date

casperc13:07:26

The include macros thing doesn't work for me at least, so I have to change the imports to (:require [secretary.core :as secretary :refer-macros [defroute]] [goog.events :as events] [goog.history.EventType :as EventType]) (:import goog.History)

casperc13:07:42

(History.) still fails

casperc13:07:56

So I don't know what I am missing 😞

robert-stuttaford13:07:59

we use (:import [goog.history History]) and it’s fine

casperc13:07:15

Maybe it is something with the version of cljs maybe,

casperc13:07:29

I am on [org.clojure/clojurescript "0.0-3211"]. Can I ask for your version?

dnolen13:07:56

@casperc: your :import is still not right, (:import [goog History]) is probably what you want

casperc13:07:27

Yeah that one doesn't complain, but (History.) is still giving the error: ExceptionInfo #<TypeError: undefined is not a function> clojure.core/ex-info (core.clj:4403)

dnolen13:07:05

@casperc: then you need to put on your debugging hat.

dnolen13:07:18

somehow goog.History is not getting required

dnolen13:07:40

examine the generated source, you should see a goog.require(“goog.History”) at the top of the file.

dnolen13:07:43

if you don’t something is wrong.

casperc13:07:58

@dnolen: Right simple_smile The Source looks like this: goog.provide('sagsbehandler.routes'); goog.require('cljs.core'); goog.require('goog.History'); goog.require('goog.history.EventType'); goog.require('goog.events'); goog.require('secretary.core'); (new goog.History()); //# sourceMappingURL=routes.js.map

casperc13:07:05

Which seems ok

casperc13:07:25

I am thinking it could be a repl problem

dnolen13:07:48

in your browser JS console try new goog.History()

casperc13:07:53

That works fine, and I just tried calling it when loading a page and it does it to work fine there.

casperc13:07:09

So I think I got fooled by a repl problem actually

casperc13:07:40

Are JS classes and the REPL not friends?

dnolen13:07:06

in your REPL wrap the expression in (fn [] …) to see the generated code

arnaudsj13:07:21

Hi, what’s the forward looking way to include a pure JS lib in a clojurescript project? CLJSJS still a good option? Or is there a something little bit less ceremonious?

dnolen13:07:07

@arnaudsj: I can’t think of anything less ceremonious than CLJSJS, you completely avoid manual configuration

casperc13:07:39

@dnolen: (fn [] (History.)) becomes: #<function (){ return (new goog.History()); }>

arnaudsj13:07:58

@dnolen: I meant that the lib in question does not exist in the CLJSJS repo, so it appear I need to write an extern file for it (or am I wrong?)

dnolen13:07:28

@casperc: so something is wrong with your assumptions. I would enable stop on breakpoints in your browser to see what is actually happening. I would disable source maps for this.

dnolen13:07:51

er "break on exception"

dnolen13:07:25

@arnaudsj: the first thing you should determine if Closure does not have the functionality of the library you are interested in.

arnaudsj13:07:20

@dnolen: I am looking at https://github.com/jstat/jstat which is neat stats library, and I don’t think I have seen this in Clojure land (incanter does have some of the things I want, but I did not think incanter could be brought into CLJS land)

arnaudsj13:07:01

in particular I am interested in the Beta distribution implementation for sampling.

dnolen13:07:05

@arnaudsj: ah cool, yeah you need externs to use that.

mikethompson13:07:23

@casperc: does this working code help? https://github.com/Day8/re-frame/blob/master/examples/todomvc/src/todomvc/core.cljs No wait. My Slack session has just caught up and I can see a LOT of discussion since you asked. So ignore this.

arnaudsj13:07:43

@dnolen: ok, let me give it a shot then, if I am successful i will send a PR. Thanks!

adwelly13:07:42

How do you create a uuid in clojurescript ? I'm getting (random-ui id) var not found errors in figwheel/0.0-3211

casperc13:07:52

@dnolen: So I am pretty sure it is a REPL problem. I am pausing on all exceptions in the browser and it doesn't break. But I tried defining the funtion to print the History object and it is actually printing it while throwing the exception in the REPL.

adwelly13:07:19

That should be (random-uuid)

dnolen14:07:23

@casperc: what REPL are you using?

casperc14:07:44

Figwheel's REPL

dnolen14:07:45

@adwelly: sounds like you don’t have the right ClojureScript dependency

dnolen14:07:19

@casperc: I would try this with a regular ClojureScript REPL a la Quick Start

dnolen14:07:28

if it works then it’s a Figwheel bug

casperc14:07:37

It does seem like it, because everything else seems to work, but I'll give it a go in a clojurescript REPL and make a bug report fir figwheel if it ends up being the problem

casperc14:07:44

Thanks for the assistance simple_smile

roberto14:07:27

I would create a sample reagent project using the lein template and compare my core.cljs with their core.cljs.

adwelly14:07:22

I've tried requiring cljs.core and also (core.cljs/random-uuid) but no joy

adwelly14:07:59

Figwheel seems to be working perfectly in all other respects though

adwelly14:07:21

Largish web app running in it without problems

dnolen14:07:35

@adwelly: what version of ClojureScript? pretty sure random-uuid is 3308 only

adwelly14:07:38

@dnolen 0.0-3211 - aha!

dnolen14:07:03

yeah random-uuid is brand new

adwelly14:07:09

@dnolen, @roberto, @casperc Thanks for the advice. I will give this a try

dnolen14:07:49

cljsinfo is doing an amazing job documenting exactly when things are added or removed.

adwelly14:07:55

...and there was me thinking I had the latest...

tcrayford14:07:58

waoahahahahahah

andrewhr14:07:24

Not enough 👍 to @maria

curtosis15:07:04

is there a recommended best practice for adding “vendor” js libraries to a cljs project? (e.g. foundation.js, jquery, etc)?

curtosis15:07:47

ahh, yes. now I remember. simple_smile sadly, no foundation.js and family 😞

curtosis15:07:04

I’m transitioning from a cljs prototype I did several months ago to a piece of a luminus project, and I haven’t made all the mental mappings yet.

curtosis15:07:46

so if there’s something not in cljsjs yet, how should I integrate/refer to it?

curtosis15:07:36

fwiw I’m porting over a page template from liftweb, so I’m hoping to avoid rewriting it completely on this pass.

troyclevenger15:07:06

@curtosis: I use this to work with some JS libraries that I wrapped myself. Allows me to keep them in git. https://github.com/LonoCloud/lein-voom

curtosis15:07:01

hmm… I suspect it’s the wrapping bit that I need more than the artifact bit… I already have a local repository in my git project for those two 3rd-party java libraries that aren’t online. lein-voom seems to solve that problem, differently?

troyclevenger15:07:58

@curtosis: Yeah it allows me to treat my git repos like clojars, at least that's how I'm using it.

curtosis15:07:00

so I think I need something kind of like this: https://github.com/clojure/clojurescript/wiki/Packaging-Foreign-Dependencies with the caveat that right now I don’t actually need to access them from cljs . I just need the foundation calls in the page template to work. cljsifcation to come later simple_smile

troyclevenger15:07:09

@curtosis: I used this to help me get started generating the externs. It's not perfect, but it helped. http://www.dotnetwise.com/Code/Externs/index.html

curtosis15:07:24

do I even need the externs, though? I think at this point all I’m trying to do is get bog-standard js libraries copied over into the resources/public/js directory controlled by cljsbuild.

curtosis15:07:37

so perhaps it’s just as simple as a :libs entry under the :compiler key? hmmm….

troyclevenger15:07:47

Those would have to be closure compatible though.

curtosis15:07:11

because it’s going to try to compile it all together?

curtosis15:07:27

even though it’s not referenced from clojurescript?

troyclevenger16:07:50

If it's not referenced, what is it being used for? I got by without externs at first, but once I tried to do advanced compilation I had to generate some. Otherwise the Closure compiler gets cranky.

curtosis16:07:06

in the simplest case, the page template loads up foundation.alert.js, and calls $.foundation() to bind to the alert box onClick.

curtosis16:07:19

very basic old-school.

curtosis16:07:37

another way to think about it is that this is (currently) a clj ring app that includes JavaScript. The cljs side comes later.

curtosis16:07:33

so the question could be better framed as "how do I include static js resources for html pages served by ring"

curtosis16:07:13

short of just including links to cdn versions. :p

dnolen16:07:33

@curtosis: Ring has static resources middleware

curtosis16:07:20

@dnolen: right... I think luminus hijacks the default resources/js directory for cljsbuild. But thinking about it now I don't see why I can't use a different directory for the static (non-closured) stuff.

roberto16:07:30

you can use compojure.route/resources

curtosis17:07:13

@roberto: there’s one of those in the default luminus template (route/resources “/“) that is presumably mapped somewhere to resources/public?

roberto17:07:36

i don’t know. I’ve never used Luminus

roberto17:07:15

if route == compojure.route, then it should be

curtosis17:07:58

>By default, any resources located under the resources/public directory will be available to the clients. This is handled by the compojure.route/resources handler found in the <app>.handler namespace:

curtosis17:07:10

(defroutes base-routes
  (route/resources "/")
  (route/not-found "Not Found"))

roberto17:07:22

so, you want to have access to a js library, for example a vendors/jquery.js ?

roberto17:07:54

you should put that folder under resources/public

roberto17:07:03

then you can refer to it as /vendors/jquery.js in your html

roberto17:07:38

so, the ‘/‘ is resources/public

curtosis17:07:42

I think that's where the discussion has led me today, yep simple_smile

curtosis17:07:27

yeah... that's the mapping I'm not clear on, though. where the "/" -> "resources/public" mapping is stored. I can work around it, but I'd like to know where the magic is.

curtosis17:07:46

If I wanted untraceable magic, I'd be using rails.

roberto17:07:04

it states there

roberto17:07:21

the root prefix path of the resources, defaults to ‘public’

roberto17:07:17

The luminus docs also says it :

By default, any resources located under the resources/public directory will be available to the clients. This is handled by the compojure.route/resources handler found in the <app>.handler namespace:

roberto17:07:52

i thought that route/resources itself wasn’t working for you

curtosis17:07:21

ok, sure. I guess it could be clearer, since to properly make all those connections you have to know that: a) resources/route has a default :root parameter b) that path is relative to resources/

curtosis17:07:23

and, specifially wrt luminus, that c) resources/public/js is managed (and cleared) by the cljsbuild process

curtosis17:07:19

looks like b) comes from lein-ring :resources-path defaults to resources/

curtosis18:07:42

or rather, that's leiningen's default; lein-ring just uses it as the base dir.

curtosis18:07:45

definitely re-thinking my choice to start from luminus rather than building it up library-by-library. 🍸

curtosis18:07:57

but yes, dropping things into a resources/public/vendor directory worked like a charm. simple_smile thanks for the many pointers leading me there.

roberto18:07:41

I haven’t used luminus before. It does look odd to me that it re-writes public/js

curtosis18:07:41

yeah... here's a bit from project.clj:

curtosis18:07:49

:clean-targets ^{:protect false} ["resources/public/js"]
  
  :cljsbuild
  {:builds
   {:app
    {:source-paths ["src-cljs"]
     :compiler
     {:output-dir "resources/public/js/out"
      :externs ["react/externs/react.js"]
      :optimizations :none
      :output-to "resources/public/js/app.js"
      :pretty-print true}}}} ...

curtosis18:07:49

I'm not too far in, so I'm still considering a ground-up, one-library-at-a-time rebuild.

curtosis18:07:14

the benefit of knowing where all the plumbing is is nontrivial

martinklepsch18:07:23

@tonsky: "In ClojureScript #datascript/DB handler is installed by default, just use … ” really? That sounds strange to me. Is datascript/DB something that’s explicitly handled in CLJS?

Niki18:07:54

No, if you’re using DataScript, of course

Niki18:07:09

DS just populates global CLJS tags table

martinklepsch18:07:58

Ah, ok. I misread then simple_smile

Niki18:07:04

Reformulated: > In ClojureScript #datascript/DB handler is installed globally when using DataScript, so read-string just works:

colin.yates18:07:12

hi all - do the optimisations make any difference to run-time performance for ClojureScript or is it just about filesizing/combining? Objective or anecdotal experience is fine 😉

Niki18:07:54

×2 improvment

andrewmcveigh18:07:02

Yes, advanced is faster

Niki18:07:26

It’s strange, but almost always when I measure it’s about ~2 times faster under advanced

Niki18:07:34

the number is very consistent

colin.yates18:07:58

OK, two out of two for faster - thanks!

Niki18:07:44

I also remember @dnolen mentioned that that’s mostly thanks to CLJS compiler optimizations, not because of Google Closure

Niki18:07:57

gclosure is just minification

Niki18:07:19

but I believe it should do some inlining too

luke18:07:02

No, gclosure under advanced mode does more than just minimization. It does inlining as well as several other algebraic code transforms.

luke18:07:32

In certain pathological cases it can be dramatically faster. It's about 6x faster than identical code when running Enlive in cljs.

spiralganglion19:07:38

In an intense HTML canvas project I was hacking on a few months back, advanced made the difference between sadness and 30fps

Niki19:07:26

Ok, shameless self-promotion: DataScript now has a Tips & Tricks wiki page https://github.com/tonsky/datascript/wiki/Tips-&amp;-tricks

dnolen19:07:52

@luke: advanced really doesn’t buy you anything at all in terms of perf

dnolen19:07:03

most closure elimination happens in simple

dnolen19:07:23

inlining does matter at all, and a lot advanced inlining is hurtful because callsites become megamorphic

dnolen19:07:44

after having benchmarked tons and tons of code

dnolen19:07:00

:simple + :static-fns true is the fastest combination across all major JS runtimes

dnolen19:07:00

previously JavaScriptCore and Firefox didn’t do property caching so the namespace pattern hurt you, but far as I can tell this hasn’t been the case in a long time

dnolen19:07:01

the primary advantage of :advanced is code size

dnolen19:07:47

this said :static-fns and :optimize-constants don’t kick in until :advanced because they interact badly with REPL driven development

dnolen19:07:04

so you have to use them explicitly when using :simple

dnolen19:07:12

just clarifying that the real ClojureScript perf optimizations are handled by ClojureScript not Closure.

Niki19:07:22

is there a way to turn off inlining in advance mode but keep minification?

luke19:07:48

@dnolen then how come I have observed 2-6x perf increases between :simple and :advanced?

dnolen19:07:02

@luke: I already explained that above

dnolen19:07:42

:advanced permits ClojureScript to generate more aggressive code.

luke19:07:51

ah, sorry, missed that. Thanks.

luke19:07:06

so much to keep up with in CLJS. Turn my back for a month and everything's different 😛

dnolen19:07:27

@luke a lot of these optimizations are actually years old

dnolen19:07:32

but I never explained them anywhere

dnolen19:07:55

actually StrangeLoop once, but not sure how many people have seen that

dnolen19:07:04

but that was 2 years ago

luke19:07:06

yeah, that stuff should probably be documented at some point. I need to sit down with you at some point (prior to the next release of the CLJS book) and get a brain dump on that kind of thing.

dnolen19:07:28

@luke more than happy to oblige

annapawlicka21:07:51

@dnolen: yoyo! any suggestions on how to compare qualifiers? i only compared major and minor and got bitten by the qualifier part. alpha versions of 1.7.0 wont work with cljs but beta will. I can compare strings by mapping them to numbers same way maven does, but that will add a few lines more and Alan Kay would not be happy about that 😉

dnolen21:07:34

@annapawlicka: I think we should just assume the known qualifiers that have been used, “alpha”, “beta”, “RCN"

dnolen21:07:43

there’s never really been others

annapawlicka21:07:50

cool, that’s only 3 instead of 7

markbillie22:07:03

Hey there, sort of a beginner question here. We (company I work for) are transitioning over to CLJS/Om. Looks like the standard Chestnut app boilerplate calls (sh "lein" "less" "auto") inside the start-less function, meaning it never kills off the child lein processes and they build up over time. NBD to kill them but I am wondering 1. if any of you have experienced this before and there is a generally-accepted solution 2. if any of you are aware of a relatively clean way to check if the lein less auto process is already running before invoking it again (iow not accepting the output of ps and testing a regexp against the string returned from the sh function) Sorry if this is old/newbish/etc, I wasn't able to figure this out by googling but assumed it must be a relatively common thing in CLJS dev environments