Fork me on GitHub
#clojurescript
<
2015-07-30
>
dimovich13:07:03

what's a good introductory book / guide for clojurescript web dev?

meow13:07:35

I'm working on a core.async example for the wiki if anyone wants to help with it: https://github.com/clojure/core.async/wiki/Sieve-of-Eratosthenes

meow13:07:03

I'm getting stack overflow errors when I try to consume 7000 primes in a repl using (time (consume 7000 (chan-of-primes)))

angusiguess14:07:12

@meow: What if you change consume to:

angusiguess14:07:59

(defn consume [n ch] (take n (repeatedly #(<!! ch))))

curtosis14:07:28

any tips for why an uberwar-deployed app would barf with "[Error] ReferenceError: Can't find variable: goog (anonymous function) (app.js, line 1)" ? It looks to me like advanced compilation didn't run, but this is my first time trying to deploy to tomcat.

meow14:07:02

@angusiguess: To get a timing value I need to eliminate the default lazy behavior of clojure, that's why I defined it as:

(defn consume [n ch]
  (dorun (repeatedly n #(<!! ch))))

curtosis14:07:13

there's even a js/out directory, which shouldn't be there if it was picking up the :uberjar profile settings. Or at least that's my weak understanding of it so far.

curtosis14:07:51

yikes... If I try and run lein uberjar I get: Compiling "resources/public/js/app.js" failed. Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.io.ByteStreams.limit

curtosis14:07:33

this is a mostly-ootb luminus project, fwiw

curtosis15:07:55

lein deps :tree to the rescue... something was pulling in a really old version of guava, so at least now it compiles in advanced mode.

curtosis15:07:10

but ring-uberwar doesn't seem to be picking that profile up.

curtosis15:07:36

confirmed... lein uberjar runs advanced compilation, which gets bundled by ring uberwar, but uberwar won't do the advanced if it's run clean.

spinningtopsofdoom15:07:20

@dnolen: When you have time could you look into applying the patch for CLJS 836? http://dev.clojure.org/jira/browse/CLJS-836

dnolen15:07:41

@spinningtopsofdoom: hrm weird have you ever submitted a CA?

dnolen15:07:09

@spinningtopsofdoom: applied thanks for the bump

dnolen15:07:25

@spinningtopsofdoom: there’s also a #C07UQ678E chan simple_smile

spinningtopsofdoom15:07:03

ah did not know that thanks!

mhuebert18:07:55

based on http://dev.clojure.org/jira/browse/CLJS-1363, we can pass a namespace to compiler options in cljs.js. given the default of ’cljs.user, guessed I could write something like :ns ‘my-app.core, but then I see Assert failed: (ana/ast? sym). Should this just work out-of-the-box or is there something special to do to prepare?

dnolen19:07:57

@mhuebert: need more info what precisely did you try + stack trace

arohner19:07:08

this might be a stupid JS question, but does ‘undefined? work on js variables?

arohner19:07:38

I’m trying to use google analytics, and (when (not (undefined? js/ga)) …) is giving me: Uncaught ReferenceError: ga is not defined

dnolen19:07:50

@arohner: you want exists? to do that

dnolen19:07:53

feature detection

dnolen19:07:23

will look into it

dnolen19:07:15

@arohner: compiles to typeof x != “undefined” which is safe from blowing up if x doesn’t exist

dnolen19:07:43

which means exists? has to be a macro btw

dnolen20:07:42

@mhuebert: took a second to test that, cannot reproduce your issue, if you can provide complete steps to repro with master I will take a look.

fluke77720:07:39

did anyone here have any luck doing some live development with github's electron. Figwheel style?

martinklepsch20:07:31

fluke777: also curious

fluke77720:07:09

martinklepsch: Just tried to run the flappy bird demo and wonders. Works like a charm. I will experiment with this a little more I have some node dependencies I would like to have. Will let you know here.

fluke77720:07:35

martinklepsch: If you are interested

martinklepsch21:07:21

fluke777: totally, please do!

arohner21:07:55

is aget the proper (and only?) way to access non-CLJS JS in advanced compilation?

arohner21:07:07

i.e. (aget js/window “foo”)

arohner21:07:34

this is 3rd party JS that I don’t own

meow21:07:43

@arohner: you should use goog.object/get - aget is only for arrays - see: https://github.com/cljsinfo/cljs-api-docs/blob/catalog/refs/cljs.core_aget.md

arohner21:07:49

@meow: thanks. For my own understanding, why should I use goog.object/get?

meow21:07:27

@arohner: tl;dr - because @dnolen says so 😉

meow21:07:05

seriously, though - aget is meant to mimic the functionality of Clojure, where it only works on java arrays

meow21:07:09

the fact that it works on other types now in cljs is not by design and might go away in the future for compatibility with the concept of Clojure and for type-based performance gains

meow21:07:04

the goog namespace is always available since cljs uses the goog closure compiler so it is a good choice for things like this

meow21:07:17

goog.object is for interacting with js objects, and has methods like get and getValueByKeys that will perform well and work across all browsers

meow21:07:07

@arohner: ask away if that doesn't answer all your questions

meow21:07:30

@fluke777 and @martinklepsch: someone recently posted a link to something for electron based on work done by @shaunlebron and @chrisoakman on cuttle or something.

fluke77721:07:19

@meow: awesome, thanks

meow21:07:25

I can't find it with a google search but I know I just saw something about it like maybe yesterday

dnolen21:07:48

@arohner: using aget incorrectly in the future will likely result in a type warning similar to arithmetic

dnolen21:07:26

there’s really no reason to abuse aget when you have goog.object/get and a lot more

dnolen21:07:14

Google Closure namespaces everyone should know about

dnolen21:07:24

goog.string, goog.array, goog.object

fluke77722:07:36

@meow: Thank you for the effort. Will check it out

meow22:07:46

@fluke777: np - let me know what you think as electron is something I'd like to get into at some point

shaunlebron22:07:11

aset and aget remain the simplest way to access js properties. using goog.object/get and getValueByKeys and set do the same thing in a more verbose way

shaunlebron22:07:58

and no multi arity set in goog.object

chrisoakman22:07:41

We need to update Cuttle.

chrisoakman22:07:00

I'll try to get that this weekend or next week sometime.

nullptr22:07:39

goog.object/get is not exactly the same — it adds an extra in check, as its real purpose to exist is for the optional arg — i think it’s worth considering something like oget in core which skips the extra check and signals intent clearly

shaunlebron22:07:51

another vote for oget @dnolen

dnolen22:07:41

not going to happen no matter how many people ask for it

dnolen22:07:56

goog.object exists, Google uses this namespace for everything

dnolen23:07:50

I find it hard to believe that Google didn’t get their core namespaces right

chrisoakman23:07:12

I've always used aget for JS object property access; is this not recommended?

chrisoakman23:07:16

I always liked that it compiled down to bracket notation using strings.

nullptr23:07:22

it’s possible that the compiler could optimize it in the absence of opt_val, at which point they are equivalent and oget makes no sense

shaunlebron23:07:55

@dnolen just saying that parts of cljs core library already wrap goog functionality for convenience to cljs users

chrisoakman23:07:58

JS strings are always safe for the Google Closure Compiler in any compilation mode (I believe)

nullptr23:07:38

yes, it’s quite commonly used for non-externed json stuff

nullptr23:07:48

in js terms, foo.bar vs foo[‘bar’]

dnolen23:07:00

remember to separate the problem from any particular solution

dnolen23:07:23

aget is not a solution to the extern problem, it’s just a hack that work

nullptr23:07:40

agreed, aget is a hack

dnolen23:07:48

people keep asking for oget and seem completely unaware that goog.object is a thing which has more

dnolen23:07:00

people need to start looking very seriously at Closure provides

dnolen23:07:16

weird JS interop helpers just keeps that from happening

dnolen23:07:39

plus I hate oget simple_smile

dnolen23:07:41

worst name ever

nullptr23:07:54

goog.object.get solves the problem, but it exists to solve a different problem — it’s a subtle point :)

chrisoakman23:07:15

it should clearly be named: get-javascript-object-property 😉

dnolen23:07:20

@nullptr: the real problem is the externs problem, and I’ve already said multiple times we’re working on that

dnolen23:07:38

but that’s larger effort which isn’t going to be band-aided by some short-term thing

nullptr23:07:09

dnolen: i hear you — we have tens of thousands of closure (js) code here, and there’s tons of foo[‘bar’] that’s not externed

meow23:07:38

(def goget goog.object/get) -->> Just Kidding!!!!!

shaunlebron23:07:44

all im thinking about is UX for new cljs users. having a dead simple function for a common interop reqt

nullptr23:07:54

it’s nice to have the option — if you just need access to one thing, externs can be a lot of extra overhead — again goog.object/get works — just seems mildly hacky (as is aget)

nullptr23:07:11

(hacky because it is only there for the opt_val support)

dnolen23:07:20

anyways I don’t have anything more official to say about it

dnolen23:07:31

use goog.object/get

nullptr23:07:42

so yeah, externs solve the problem, but not always the most convenient thing

dnolen23:07:44

in the future property access on foreign values will work you won’t need all this stuff

dnolen23:07:03

we will generate externs for you

dnolen23:07:00

likely there will need to be a corresponding ^js if people are doing fancy higher order things

shaunlebron23:07:07

arbitrary json objects though

dnolen23:07:38

arbitrary json … this is what goog.object is for

dnolen23:07:51

totally different from the foreign library thing

dnolen23:07:56

which is way more painful

shaunlebron23:07:43

ux for new users is all im arguing for. simple multi-arity functions

dnolen23:07:27

I’m just not concerned about this problem at all

dnolen23:07:33

doc this in all the right places

dnolen23:07:37

and new users will know what to do

dnolen23:07:48

it’s also the case that in watching what developers actually do w/ ClojureScript, they convert JS data immediately

dnolen23:07:19

few people want to manipulate JS data directly (except maybe arrays) because the tools are so weak compared to ClojureScript data

dnolen23:07:45

investing in things only new users are going to use

shaunlebron23:07:33

i mean, i guess this is a bigger discussion about convenience replaced by complete documentation

shaunlebron23:07:18

but i was working with people who just wanted to manipulate js options map as fast as possible

dnolen23:07:26

“as fast as possible"

dnolen23:07:32

for what purpose?

dnolen23:07:43

are they actually in an inner loop with 10+ million iterations

dnolen23:07:46

if not waste of time

dnolen23:07:25

if they are and it’s that important then writing an extern is the right answer and takes no time at all

dnolen23:07:22

if this is “JS-think” then I’m not really sympathetic to that

shaunlebron23:07:36

i never saw the code actually. there were just noticeable performance hits in creating cljs data structures and converting to js data. i think with clj->js

dnolen23:07:11

what I mean is was the perf hit like

dnolen23:07:19

“let me measure this part of my program that doesn’t matter"

dnolen23:07:28

oh the part of the my program that doesn’t matter is 10X slower than the JS

shaunlebron23:07:29

right i get that

dnolen23:07:34

let me optimize this thing that doesn’t matter

dnolen23:07:39

it’s bonkers

dnolen23:07:44

not going to support that mentality at all

shaunlebron23:07:51

this was just a side point. the only thing i care about is not telling new users that to do such a simple interop thing by importing three functions from goog.object

dnolen23:07:14

this is just a non-goal

dnolen23:07:24

new comers should know about goog.object

dnolen23:07:55

if the talking about the awesomess of Google Closure isn’t the first thing covered something is not right w/ the docs

shaunlebron23:07:00

we will have to add that to cljs-api-docs in some capacity

dnolen23:07:43

the fact that new users never have to include an additional dep for basic functionality is something to celebrate not hide

arohner23:07:39

@dnolen: as a newcomer, I heard the “Closure is awesome” part, but for some reason the “you are expected to know Closure’s standard lib the way you are expected to know Java’s when using CLJ” was not obvious to me

arohner23:07:59

I thought “Closure is awesome” referred to the compiler, not the stdlib

dnolen23:07:20

@arohner: if you rewatch the original ClojureScript announce that’s not what Rich Hickey said simple_smile

dnolen23:07:58

but I agree the messaging over all should be improved and more clear

dnolen23:07:59

yes if people see docs where this isn’t be done correctly please fix

dnolen23:07:08

I’ve started switching my own libs away from the old style

nullptr23:07:39

at least we can all agree that aget is terrible! i can’t tell you how long it took me to figure out that it was “the way” to do that before it wasn’t… exceedingly non-obvious

mhuebert23:07:37

@dnolen: I’ve put two examples in a clean repo- https://github.com/mhuebert/def-in-ns/blob/master/src/cljs/foo/eval.cljs evaling ‘(def x 1) with :ns set to ‘foo.other, an existing ns, compiles to “.x = 1” evaling ‘(do (ns foo.totally-new) (def x 1)) compiles to "(function (){\ngoog.provide('foo.totally_new');\ngoog.require('cljs.core');\n\ncljs.user.x = 1;\n})()\n”

dnolen23:07:23

@mhuebert: neither of those example are actually valid though. you never created the namespace first

dnolen23:07:01

sorry rather the first one is never going to work

dnolen23:07:08

we’re not going to magically create a namespace for you.

mhuebert23:07:24

@dnolen so it doesn’t see that I created the other namespace elsewhere? (`(ns foo.other)` in cljs/foo/other.cljs)

dnolen23:07:46

@mhuebert: if you already made it yes that will work

dnolen23:07:55

but your example doesn’t demonstrate this clearly at all

dnolen23:07:07

I have an example in ClojureScript master right now that works

mhuebert23:07:09

sorry, I linked to the eval file.

mhuebert23:07:20

it’s in the dir with core & other

dnolen23:07:39

@mhuebert: ah so I didn’t really understand what you are trying to do

dnolen23:07:49

it’s important to be very specific about what you’re attempting

dnolen23:07:10

you want to build a project and then eval inside that project’s namespace at runtime

mhuebert23:07:37

I’m having success as long as I only want to eval in cljs.user,

mhuebert23:07:50

moderate success at passing in some helper functions there that eval can access

dnolen23:07:33

@mhuebert: also figwheel is a really undesirable thing

dnolen23:07:44

I’m not going to look at anything that isn’t actually minimal

dnolen23:07:49

massive time sink for me

dnolen23:07:58

I only want to look at something with zero deps

mhuebert23:07:20

understandable, I can take that out

mhuebert23:07:38

does leiningen cause problems?

dnolen23:07:47

@mhuebert: anything that isn’t minimal causes problems

dnolen23:07:07

ClojureScript is plenty fancy enough as it is

dnolen23:07:18

introducing additional variables is a productivity killer

dnolen23:07:44

@mhuebert: in anycase, make a real minimal example ping me and I will look at it