Fork me on GitHub
#clojurescript
<
2015-09-19
>
ericnormand01:09:45

I'm having trouble getting doo to test in chrome

ericnormand01:09:51

has anyone gotten it working?

vikeri08:09:48

Nice meeting you too @martinklepsch ! Disappointed there's no Rubby channel here ;)

sveri09:09:35

Hi, I am trying to use cljs for screeps (programmable game in the browser), I just cannot get it done. I am using advanced compilation and just try to export one simple function: https://github.com/sveri/screeps/blob/42366307b9101c3a01c8a1bca2ef416c650cd1bd/src/screeps/core.cljs and this is the compiled js: https://github.com/sveri/screeps/blob/42366307b9101c3a01c8a1bca2ef416c650cd1bd/js/screeps.js. My namespace is screeps.core and when I do a `require ('screeps.core'); from js side it cannot find the module. Is it even possible to load namespaces like this from js? Directly calling the function with screeps.core.startscreeps.start(); does not work either. Any ideas / suggestions?

jaen09:09:50

Hmm, requires won't work, GClosure modules are not CommonJS modules but screeps.core.start() should work though.

sveri09:09:37

jaen: it says: ReferenceError: screeps is not defined and I got the feeling that the export does not work properly, at least I cannot find a functioned named start in the compiled js

sveri09:09:17

What I see in the compiled js is: function Ie(){return console.log("foooooooooo")}var Je=["screeps","core","start"], but I would expect a function named start with a namespaces defined.

jaen09:09:40

Are you sure it is not working?

jaen09:09:45

I just compiled your project

jaen09:09:59

Opened the index.html in the web server

jaen09:09:04

And could call the function.

pupeno09:09:43

How can I write this code in ClojureScript:

pupeno09:09:48

var server = app.listen(3000, function () {
  console.log('Example app listening at ', server.address().address, server.address().port);
});

martinklepsch10:09:29

@pupeno: (def server (.listen app 3000 (fn [] (js/console.log …. (.-address (.address server)))))

martinklepsch10:09:53

something like that

martinklepsch10:09:16

oh, are you also asking about string interpolation?

pupeno10:09:17

martinklepsch: that requires having that as top level, so that app should also be defined as a top level, so they are both global variables, which I’d rather avoid.

pupeno10:09:42

No, not string interpolation, but about that function having access the the return of .listen.

martinklepsch10:09:06

don’t really understand the question yet...

pupeno10:09:47

I don’t want to def server.

pupeno10:09:28

I want it as a local variable.

jaen10:09:58

Won't putting it in a let work then?

martinklepsch10:09:32

That’s what I’m thinking too but it can’t be that easy 😛

pupeno10:09:22

jaen: no, at the time the function is defined, whatever let will set didn’t happen yet.

pupeno10:09:55

That little JS code depends on having variables 😞

jaen10:09:51

Hah, maybe there is a letrec macro for Clojure somewhere?

pupeno10:09:51

"No letrec, labels or flet - use (fn name [args]...) for self-reference, letfn for mutual reference.” http://clojure.org/lisps

pupeno10:09:26

There’s a letfn but it assumes you are defining functions.

jaen10:09:49

TFW you wonder why project won't work and you misspeled clojars to cojars` when deploying. Funny it did let it deploy then though.

jaen12:09:31

Another chapter in trying to get those damn CommonJS modules workng is here. This time with boot and reagent - https://github.com/jaen/react-with-modular-cljs. Doesn't yet handle all conceivable npm libraries (no support for things like name and main yet) and you need to use mangled names, but hey - it's something!

timgilbert14:09:38

@pupeno: don’t think you can do that with purely-lexical binding. You wouldn’t be able to do it with a let server = … in ES6 either, as far as I can figure

timgilbert14:09:11

I think in ClojureScript you’d need to use (set!)

edvorg14:09:20

Hi every one. I set up clojurescript dev environment from figwheel template. It works just fine out of the box. I tried to connect to my dev machine from outside from my android device. The problem is (fig-status) shows me that there is no client dev connections and consequently reloading doesn’t work.

edvorg14:09:11

How could I manage it?

jaen14:09:41

I think it connects to localhost by default (though it's a while since I used figwheel)

jaen14:09:07

You can try setting the :websocket-host option to the IP of your server

edvorg14:09:13

Awesome, it works. Thank you @jaen

jaen14:09:09

No problem

bhauman16:09:34

I have been working on articulating the why of Devcards a bunch lately https://github.com/bhauman/devcards#why

bbss16:09:54

I had seen devcards before, but didn't think of these advantages, very convincing. Going to give them a go in my recently started blog simple_smile

bhauman16:09:50

@borkdude: I'm guessing you read it ;)

borkdude16:09:18

@bhauman: I just read it but I personally don't see the benefit yet to be honest simple_smile

bhauman17:09:12

That's cool. You will ;)

borkdude17:09:52

@bhauman: probably when I'm building more sophisticated components. I see the history thingy: that's cool

bhauman17:09:40

@borkdude: you know that means I just have to do a better job on the why section.

bhauman17:09:57

@borkdude: after figwheel, I'm accustomed to folks saying "what's wrong with just reloading the browser?" Not that devcards is the same, but to me it is. Even the lowly todo item has a way more states than we normally give it credit for.

borkdude17:09:26

@bhauman: haha, true.

borkdude17:09:58

@bhauman: Add that line to the why section, it's a good one simple_smile

bbss17:09:13

That is the thing that struck me the most in the why section, I have recently been thinking I should find a way to visualize whatever problem I am solving, whether it will be data that ends up looking pretty in the ui or not. And being able to save that problem solving process is super valuable documentation plus it can be used as a base for tests.

borkdude17:09:26

@bhauman: thinking about it, I could see it being useful testing how a component looks in different states and if the CSS is still good

borkdude17:09:17

@bhauman: because I have been working with a CSS designer and he could maybe use that too

bhauman17:09:47

@borkdude: yeah selenium tests, suck and they don't even tell us the very basics of whether an application is working.

bhauman17:09:16

Yes exactly you CSS designer gets to see all the edge case states

bhauman17:09:37

Including the empty state and the overflow state

bhauman17:09:18

And so do you

bhauman17:09:39

@bbs exactly, kinda strange that we are not doing this already

borkdude17:09:07

@bhauman: ok, I'm sold. going to try it out in my next project simple_smile

bhauman17:09:41

Sweet!! Now it doesn't have to be devcards but a separate app that you can throw components into works as well. Devcards just gives shape to one way of doing this.

bbloom17:09:37

does anyone know if anybody has done a js-native version of datascript?

bbloom17:09:00

or something else on the spectrum between there and relay

tonsky18:09:20

@bbloom: I guess JS binding in DataScript isn’t enough for you?

bbloom18:09:53

@tonsky: I was just looking at it - Looks solid, but it doesn’t meet my (admittedly nonsensical) requirements

bbloom18:09:36

it’s the same goofy motivations that make immutable.js popular where mori.js exists

tonsky18:09:02

just remember, when JS folks did js-native version of mori (immutable.js), turned out it was slower than cljs

tonsky18:09:17

glad you mentioned it simple_smile

bbloom18:09:21

lol yeah, you’re preaching to the choir here

bbloom18:09:33

“not scary” is on my list of requirements

bbloom18:09:27

although while i have you here, @tonsky

bbloom18:09:20

any experience report info to share? from yourself or users? especially with respect to “time travel” and queries?

bbloom18:09:24

or entities?

bbloom18:09:53

for most UI needs, i only really want/need pull-api & i don’t expect time travel to be valuable for my cache of server side data (which cant’ be time traveled from the client)

bbloom18:09:20

but 1) maybe i’m overlooking something and 2) I understand that (at least time travel) comes “for free” from immutable data structures

tonsky18:09:04

well, when implementing client/server pull, immutability comes really handy

tonsky18:09:26

because you want to temporary apply changes happened on client locally to display

tonsky18:09:38

and throw them away/reapply when you got confirmation from the server

tonsky18:09:47

e.g. Relay does that

bbloom18:09:55

right, but can you do that on a whole-database level? what happens if you have two transactions occurring in parallel?

tonsky18:09:05

don’t know if they embrace immutability internally. But they have this problem

bbloom18:09:15

eg i click “X” next to two rows in a table to delete them, each sends a separate request, and then the first of the two fails

bbloom18:09:29

don’t you need to “manually” rollback that? rather than rollback the whole cache?

tonsky18:09:30

It’s up to you to decide

bbloom18:09:35

if i were working on a cljs project, i’d select datascript w/o hesitation

bbloom18:09:55

but i think i need only a small core of it for this js project

bbloom18:09:04

although that could be ignorance

tonsky18:09:18

and when on js, you can’t live without db.q() instead of datascript.q(db)

bbloom18:09:01

what’s the difference?

tonsky18:09:20

method vs top-level fn

bbloom18:09:24

oh heh, yeah

tonsky18:09:37

that was the main motivation for immutable.js

bbloom18:09:45

i’ve said it before: the dot operator is the best/worst thing OOP ever gave to the world

tonsky18:09:03

JS devs can’t stand conj(list, el), they want list.conj(el)

bbloom18:09:13

ha, seriously

bbloom18:09:23

but there’s also the mongo-style query json obj things

bbloom18:09:42

eg the pull api or the query API are based on edn vs json

bbloom18:09:48

these subtle things affect how people perceive it

bbloom18:09:35

i’d like to say us clojure devs are enlightened, but then folks go and keyword-ize json objects in their server apps

tonsky18:09:21

speaking about experience reports: http://atomic.io uses js / immutable.js, but overall looks like a perfect fit for datascript

tonsky18:09:58

they have infinite undo/redo, persistent history, and queries over history (selective rewind over some group of objects)

tonsky18:09:03

but if you’re not building graphic editor, you probably won’t need immutable history

bbloom18:09:18

looks like a nice app

tonsky18:09:31

immutability brings a lot of sanity to the code anyways

tonsky18:09:55

you can do “big things” (like multi-step transactions) and decide not to apply them at the very end

bbloom18:09:58

again: preach/choir

tonsky18:09:09

and nothing is broken and you don’t need to clean up/roll back manually

tonsky18:09:04

a big relief

bbloom18:09:51

the .get/.set syntax on the entities is also a non-starter for many js people

bbloom18:09:12

especially folks who lived through the backbone era

bbloom18:09:40

probably impossible to avoid w/o ES6 proxies in js-land

tonsky18:09:12

what’s better alternative to get/set?

bbloom18:09:24

plain-old-javascript-objects

bbloom18:09:30

the dot operator strikes again

bbloom18:09:52

but can’t easily work with cyclic refs, etc

tonsky18:09:14

yeah, you can’t have custom logic without getter

bbloom18:09:29

but i think the pull API is more appropriate the entity or query for 9/10 UI use cases

bbloom18:09:32

b/c it’s eager

tonsky18:09:33

Immutable.js seems ok with getters?

bbloom18:09:52

i think immutable.js is misguided

bbloom18:09:04

might as well just fucking use cljs at that point 😛

zentrope18:09:44

Office politics trumps all.

bbloom18:09:45

my goal is a stepping stone towards better semantics simple_smile

zentrope18:09:46

I don't know how all these blog-posters convince their teams to use all the cool things they write about. I mean, how do you get that on the backlog?

bbloom18:09:09

most of it is “do whatever the fuck you want” inside “enlightened” overfunded tech companies

bbloom18:09:32

those of us who have woefully understaffed teams and real paying customers need to curb our enthusiasm, heh

zentrope18:09:34

Alas, that used to be the case, but Agile/Scrum has locked things down tight.

zentrope18:09:53

The technical debt creation factory is quite efficiently micro-managed. No creating debt the old fashioned way, using whacky new stuff no one understands later on! ;)

zentrope18:09:27

Immutable.js, all anyone hears is, "js", so that's a go.

bbloom18:09:46

i don’t think immutable.js is easy a sell as you think

bbloom18:09:07

slash dot operator discussion above

zentrope18:09:18

Or, really, what an engineer hears is, "Ooo, I can score 'responsibility' points by putting fear into the manager with this 'immutable' fringe-science guy."

dnolen18:09:53

well in the JS world even if you capture a error margin of the market it still means tons of users

dnolen18:09:03

nearly half a million downloads a month

bbloom18:09:03

this is true

bbloom18:09:57

but i find those numbers suspect, b/c they suggest that virtually 100% of react users use it:

dnolen18:09:25

@bbloom: they are inflated of course because of the way NPM works, but still

bbloom18:09:37

poorly? zing

bbloom18:09:44

anyway - i think i’m going to create a project to spoon feed additional good ideas to the js community

tonsky18:09:56

always a good idea simple_smile

bbloom19:09:38

back in the future…. @dnolen are you totally sold on the idea of sending pull-api queries to the server from the client?

bbloom19:09:49

i think it’s a solid idea, but i think we can go one step further

bbloom19:09:51

obviously a good idea for server to send pull api data structure to the db, but from client->server it seems like you could share code w/ the server such that you only need to give the server the root get-query call

bbloom19:09:30

so instead of sending the server the expanded query, you give the server the top-level parameters, from which the server can re-create the query

bbloom19:09:57

especially since the query may be pretty large, given that every UI component has a tiny query fragment w/ it

potetm19:09:42

@bbloom: So the server returns the whole tree beneath the root?

bbloom19:09:54

no, the server would have sessions

jaen19:09:16

But sessions are so last year.

bbloom19:09:37

jaen: tech is cyclical simple_smile

jaen19:09:40

At least I see a lot of people advocating for stateless serves nowadays

tonsky19:09:41

it will mean server will need to be in sync with the client. And share the code

tonsky19:09:55

the idea of relay is that you have one universal server

tonsky19:09:03

and don’t care who your clients are

tonsky19:09:09

what versions they are on

potetm19:09:18

Also, my first question when doing pull-queries client->server is how do you do access control? I’ve yet to see what people are doing for that.

bbloom19:09:30

potetm: db.filter ?

bbloom19:09:06

tonsky: the version problem is a real one, but i’m not convinced a universal server is possible or desirable — or at least it’s not possible to avoid client-specific code, only to minimize it

bbloom19:09:19

eg you’re going to need to serve the bootstrap html code for the web version

bhauman19:09:40

access control is universally necessary

bbloom19:09:12

this is just a thought, but i’m not advocating against a universal server

potetm19:09:14

bbloom: Yeah that makes sense.

bbloom19:09:32

versions is a much smaller problem for the web - modulo long-running single-page apps that you are going to upgrade constantly & force people to refresh or whatever … it’s a big problem for mobile tho

dnolen19:09:13

@bbloom: you can just send the subquery.

dnolen19:09:43

even without transit encoding I’m not really convinced the size of the query matters that much.

bbloom19:09:56

just so i understand: how do you decide which subquery to send?

bbloom19:09:51

actually - gotta run

bbloom19:09:56

good chatting all! thx

dnolen19:09:01

because every component has the query colocated

dnolen19:09:26

if a component triggers a mutation then the router and custom logic will trigger queries to be re-run

bbloom19:09:32

oh, you’re saying you just send the DELTA of queries?

bbloom19:09:34

ok makes sense

pupeno19:09:41

A library I’m using (re-frame) uses a go-loop. I have a function that puts something in the channel this go-loop is reading and I need to stop and let that go-loop run until the channel is empty. Is this possible?

borkdude20:09:03

@pupeno: "and I need to stop and let that go-loop run" I didn't get that part

pupeno20:09:25

I need to force processing the channel until it’s exhausted before continuing doing other things in my function.

borkdude20:09:50

ok, so you want to wait until the channel is empty and then continue doing something else.

pupeno20:09:41

borkdude: yes.

pupeno20:09:05

which probably means manually processing the channel or something like that, as there’s no waiting in javascript.

borkdude20:09:58

I think you need to use mult + tap to listen to a copy of that channel

borkdude20:09:00

<! returns nil when the channel is closed

pupeno20:09:11

Yeah, this channel is never closed 😞

borkdude20:09:44

so what is the definition of empty of that channel? does it have a buffer?

ericnormand20:09:38

Fewer externs seem to be needed than just a few months ago.

ericnormand20:09:54

Has there been work on extern inference?

pupeno20:09:26

borkdude: I actually don’t know. Normally, nobody cares about that because on the browser you just render the app over time. But when pre-rendering on the server, at some point I need to finish it and ship it to the browser.

borkdude20:09:03

@pupeno: maybe you can use a timeout channel + alts

borkdude20:09:15

+ mult + tap simple_smile

ericnormand20:09:15

@pupeno: you could timeout on the <!

ericnormand20:09:48

That's a reasonable definition of "empty" for a channel that never closes

jaen20:09:56

@pupeno: so you basically need to pause your go-loop until something happens to unpause it?

pupeno20:09:23

ericnormand: there’s another signal that I have to take into consideration (whether a handler is being run), but that one is easy.

pupeno20:09:50

@jaen: no, I want a specific go-loop to run until it parks and then do something.

ericnormand20:09:26

I don't think that's possible. The current state of a go block is not available.

jaen20:09:26

But I think you could alt with a default, if you get a default the channel is empty.

ericnormand20:09:36

The only way you could spy into it is if you could mult the channel before the go loop got it, like @borkdude was saying

ericnormand20:09:34

Or something similar, of course

ericnormand20:09:42

But frankly it sounds iffy.

martinklepsch20:09:49

Maybe an alternative approach could be to emit some sort of “done” event from the app and render after that happened

pupeno20:09:59

martinklepsch: it’s impossible to emit a done signal in this case.

pupeno20:09:02

Thinking a bit more about it, I think what I want to do is wait until the channel hasn’t seen any activity for n milliseconds or the app has been running for m milliseconds.

pupeno20:09:12

Is this documentation for both clojure and clojurescript or just clojure? http://clojure.github.io/core.async/

borkdude20:09:28

both, but cljs is limited to one thread, so anything that says "blocks thread" won't work

ericnormand21:09:14

@estsauver: hey there! Thanks for the email!

dialelo21:09:26

pupeno: you can also check http://funcool.github.io/clojurescript-unraveled/#appendix-b-csp-and-core-async for a less terse documentation, we cover everything cose.async offers in ClojureScript with examples

ericnormand21:09:09

@dnolen: is ClojureScript smarter about inferring externs than it was a few months ago?

dnolen21:09:05

@ericnormand: it’s never inferred externs … so no

ericnormand21:09:07

I specifically remember having to add an extern for something

ericnormand21:09:19

and I upgraded clojurescript and now it's not required

dnolen21:09:39

for random JS stuff you still have to provide externs

dnolen21:09:51

but CLJSJS libs means someone has already done that work for you

ericnormand21:09:16

it was screen.width specifically

martinklepsch21:09:19

@ericnormand: depending on what it was an update of the closure compiler might have added an extern for the thing you added

martinklepsch21:09:33

that sounds like a likely candidate

dnolen21:09:41

yeah that too, Closure adds stuff periodically

dnolen21:09:08

now that I know how to deploy GCL updates I’ve been bumping it with more frequency

ericnormand22:09:32

@dnolen: You're welcome!

ericnormand22:09:38

going to Strange Loop?

dnolen22:09:43

personally being able to interactively test via cljs.test + a Node REPL is yet an other huge plus for me over JavaScript

ericnormand22:09:13

oh, wait, you're speaking!

ericnormand22:09:53

I totally agree

ericnormand22:09:31

lispers like feedback

bensu23:09:15

@ericnormand: did you run into any trouble while setting up doo?

ericnormand23:09:30

yeah, lots of trouble

ericnormand23:09:37

but I don't know if any of it is doo's fault

ericnormand23:09:52

I was having npm issues

ericnormand23:09:01

because I rarely use it

ericnormand23:09:08

it was probably 3 years old

ericnormand23:09:20

and I didn't realize it

ericnormand23:09:54

and there were some things I couldn't figure out with Boot

ericnormand23:09:40

but I think i figured everything out on the Leiningen side

ericnormand23:09:36

I think doo is going to be great, though