Fork me on GitHub
#clojurescript
<
2015-11-29
>
mikethompson00:11:11

@jaredly: I'd suggest you start with this brilliant bit of work: http://shaunlebron.github.io/t3tr0s-slides/#0 (a step by step guide to building Tetris in cljs). Code: https://github.com/shaunlebron/t3tr0s-slides

mfikes00:11:53

Yes, @eyelidlessness, I’ve added (def f (fn x [] #'f)) to CLJS-1495

mikethompson10:11:57

I'm puzzled by exists?. At the REPL this works:

cljs.user=> (exists? js/window)
true
But this is odd:
cljs.user=> exists?
WARNING: Use of undeclared Var cljs.core/exists? at line 1 <cljs repl>
nil
It is used in https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs but never defined.

mikethompson10:11:52

Where does it come from?

mikethompson10:11:59

@darwin: of course. Thanks!

octahedrion10:11:40

why might one of my Om components not get IDidUpdate called ?

octahedrion10:11:03

(the others do, but one of them doesn't)

darwin10:11:05

@octo221: did you put logging inside render function? is it really being re-rendered by Om?

octahedrion10:11:14

yes, IRender is being called

octahedrion10:11:36

(render [this] I mean)

darwin10:11:04

isn’t its parent being re-rerendered as well and discarding it as a child somehow? or isn’t it rendering nil or empty value? just wild guesses

darwin10:11:26

have to go, lunch time

octahedrion10:11:37

ok cheers for the ideas

octahedrion11:11:29

hey child components in general don't seem to get did-update called

darwin13:11:14

@borkdude: I believe it is using khroma library: https://github.com/suprematic/khroma, both lib and extension written by @ricardo

darwin13:11:59

@borkdude: are you planning on building some chrome extension?

borkdude13:11:42

@darwin: never thought about it, but such a library could become a gateway drug 😉

darwin13:11:19

@borkdude: well, I was asking because, just recently I have been working on a similar library simple_smile mine also covers APIs for chrome apps now: https://github.com/binaryage/chromex/

darwin13:11:21

still an early version, want to see some real usage (except for my own extensions) to iron out remaining problems simple_smile

ricardo13:11:36

@borkdude: @darwin is correct, it uses Khroma. His ChromeX is a pretty neat approach, too.

ricardo13:11:03

If nothing else, easier to maintain than having a random human make assorted, not-necessarily-consistent decisions about how to expose a particular API when he needs it. 😛

ricardo13:11:48

@darwin: I see you removed your “don’t use this because it’ll kick your pets” warning. Do you expect the API is more stable? Are you planning to add some extension-specific tests?

darwin13:11:44

big credit goes to Google developers who were so disciplined to provide automated way how index their APIs, according to my stats there is 1000+ functions in their public apis right now, zero chance anyone could cover them manually

darwin13:11:51

@ricardo: I just started building my own real extension on top of it, I don’t know about any limitations right now

ricardo13:11:22

I mean more along the lines if you expect the way you’re exposing stuff to change.

darwin13:11:10

I don’t plan extension-specific tests, that’s Google’s job simple_smile I mock simple extension apis in my tests and test just my wrappers, also I want to automate it and extension code is much harder to test automatically

darwin13:11:32

I wonder what are your plans with khroma-tests

ricardo13:11:42

I know. simple_smile That’s why I wrote khroma-tests to be half-test and half-use examples.

darwin13:11:02

kudos for using devcards simple_smile

ricardo13:11:20

I merged it into the main khroma repo. This has got me thinking I should just release it to 0.3.0 as is, so that people don’t have to look at two repositories. Going to do that now

darwin13:11:36

I will have one example project which I will maintain, there will be a “test” button to run quick battery of simple tests, but I will just use it for ad-hoc testing

darwin13:11:21

btw. here is my quick chrome API mock, seems to be ok, for simple tests for my wrappers: https://github.com/binaryage/chromex/blob/master/test/chromex/test/playground.cljs#L15-L62

darwin13:11:26

@ricardo: as API stability, I don’t know, conceptually the api won’t change I think, but I cannot guarantee it at this point

ricardo13:11:45

To me it’s less about making sure that extensions still work and more about making sure the way I expose them is consistent with what people are expecting from before.

ricardo13:11:54

Even if it’s automated, once can still break that.

darwin13:11:57

I think there will be more discoveries about marshalling specific types

darwin13:11:26

sure, if you have library users, that is a valid concern

ricardo13:11:29

There. Merged 0.3.0 to master.

darwin14:11:17

that is why I’m trying to spread a word early and get some people on board with their extensions-in-development, so we can discover issues early and stabilise the interface

ricardo14:11:14

@borkdude: If you’re looking into getting acquainted with a Clojureic way to access the API, check out the khroma tests.

ricardo14:11:03

@darwin: Well, if you’re looking into it, I can’t recommend devcards highly enough.

borkdude14:11:29

thanks, I wrote down these libraries to take a look at it later

henriklundahl14:11:45

This returns true with advanced compilation and false without (or with :pseudo-names):

henriklundahl14:11:49

(seq? (google.maps.LatLngBounds. (google.maps.LatLng. 1 2) (google.maps.LatLng. 3 4)))

henriklundahl14:11:50

Any ideas why it would return true? Some kind of name collision?

dnolen15:11:47

@henriklundahl: did you test the name collision theory by using a closure around your code?

dnolen15:11:57

:output-wrapper true I think is the compiler option

dnolen15:11:34

@octo221: there’s an #C06DT2YSY specific channel btw

henriklundahl15:11:48

@dnolen: I get the same result with :output-wrapper true...

dnolen15:11:21

it’s possible it’s an advanced optimization bug, I’ve certainly seen those now and then

dnolen15:11:29

unless you want to dig in I would just tweak your logic a little bit

henriklundahl15:11:29

The thing is I'm trying to use js->clj on the results from the Google Maps geocoder, where LatLngBounds are among the values.

henriklundahl15:11:21

...and seq? is used in js->clj.

dnolen15:11:29

@henriklundahl: yeah so I suspect that under advanced the protocol gets renamed to a property that the google map object has

dnolen15:11:22

no good answer is coming to mind other than write your own js->clj that doesn’t have the seq? or coll? cases

dnolen15:11:47

I don’t really think it should have them, but I think these were added as convenience back in the old days

dnolen15:11:04

when people were directly dealing with DOM and child nodes

dnolen15:11:56

should maybe revisit that but would need to determine how much breakage it would cause

henriklundahl15:11:41

@dnolen: But couldn't something be done about the name collisions (if that is what is happening)? Feels like anything can happen if functions or properties are overwritten?

darwin15:11:21

(a reproducible advanced mode problem with clojurescript code itself)

darwin16:11:26

if you have an instance of the same issue, then Google Closure Compiler does not connect access to .-lat nad .-lng properties (for reading) with access to them (for writing), and removes them in some cases (for example in LatLng. constructor), that leads to .equals return true when comparing both constructed objects, because it compares undefined values, … just a theory

darwin16:11:40

@henriklundahl: try to build a minimal repro case and we can try to reason about what happened there^

dnolen16:11:12

@henriklundahl: you can’t do anything about these kinds of name collisions in JavaScript period

dnolen16:11:27

library A gives semantic to object X with method get

henriklundahl16:11:27

@darwin: I think there aren't any usable properties in LatLngBounds or LatLng so I wouldn't expect js->clj to do anything with them, which is what happens without advanced compilation.

dnolen16:11:35

library B gives different semantic, BOOM

thheller16:11:51

where is the LatLng stuff coming from?

dnolen16:11:53

this happens all the time with stuff like call

henriklundahl16:11:44

@dnolen: Sure, but there are some steps before we end up with the same names...

thheller16:11:47

and the correct externs are used for that?

thheller16:11:09

kk just checking simple_smile

dnolen16:11:10

@henriklundahl: this just isn’t how Google Closure works

dnolen16:11:30

you are using a foreign library that Google Closure doesn’t know about, there’s no way to know that names won’t clash

thheller16:11:10

@dnolen if the externs are used it will now it

dnolen16:11:27

only if the externs are complete

dnolen16:11:33

including enumerating private members

thheller16:11:26

ah they only have the getters/setters

dnolen16:11:58

@henriklundahl: if you don’t want to monkey-patch js->clj then providing this information is another route

henriklundahl16:11:08

@dnolen: You mean what's missing in the externs?

henriklundahl16:11:42

But couldn't the names of those properties change at any time?

dnolen16:11:43

yes, this is why I suggested monkey-patching js->clj

dnolen16:11:50

this can’t possibly cause you any problems

henriklundahl16:11:36

But can you help me understand, what's (probably) happening?

dnolen16:11:44

or honestly writing your own conversion library that doesn’t have this problem

henriklundahl16:11:02

How can those private properties munge anything?

dnolen16:11:32

I already explained what happened, but I will say it again

dnolen16:11:58

A) ClojureScript uses properties to know what types belong to which protocols (since there are no interfaces in JavaScript)

dnolen16:11:11

B) this get renamed by advanced compilation

dnolen16:11:32

C) You are using a 3rd party library with properties the Closure Compiler does not know about and not providing externs to cover you

thheller16:11:19

interesting problem though that the renamed property contain exactly the value required to make it look like a cljs seq

dnolen16:11:48

right so we can’t fix the general problem

dnolen16:11:59

but in this case we could use a different sentinel value

dnolen16:11:05

currently it’s just true

dnolen16:11:16

but would need to measure perf implications of doing so

thheller16:11:22

isn't there a bitmask check involved somewhere?

dnolen16:11:37

only for fast path protocols

dnolen16:11:48

and that's probably not safe anyhow because of JS coercion

dnolen16:11:10

thinking about it some more Google Maps is probably the worst case scenario - since I suspect they don’t allow you to build from source and the thing you get is already advanced compiled

dnolen16:11:28

so externs might not help you anyway

thheller16:11:30

if I'm reading this right

thheller16:11:58

it only checks if the property is true-ish

thheller16:11:21

maybe that should just check true?

dnolen16:11:33

we could do that, would narrow the likelihood

henriklundahl17:11:41

@dnolen: Ok, I understand, thanks. It does feel quite brittle as it is now...

henriklundahl17:11:57

You're right about Google Maps.

dnolen17:11:10

@henriklundahl: this is the first time anyone has ever reported this issue in 4 years

dnolen17:11:01

we’ve had more bug reports about real bugs in the Google Closure compiler than challenging name clash edge cases like this

thheller17:11:13

@henriklundahl: if you just want to pass data to the google maps api and don't need to work on it in cljs you can use the #js {} reader literal stuff to directly construct js objects instead of closure maps

thheller17:11:28

so you don't need clj->js

henriklundahl17:11:23

@thheller: Yeah, I know and I do when it's possible. This time it's the other way around (js->clj), though.

henriklundahl17:11:33

@dnolen: So I guess there aren't many other situations that CLJS handles in a similar way?

dnolen17:11:23

@henriklundahl: this really just doesn’t come up that often

dnolen17:11:56

3rd library libraries use Yahoo compressor or Uglify for minification

dnolen17:11:20

this particularly bad interaction is because you have 2 Closure advanced builds compiled separately

henriklundahl17:11:23

Yeah, I know, but are there other places in the CLJS codebase that relies on object properties in a similar fashion?

dnolen17:11:24

yes all of ClojureScript

dnolen17:11:36

the whole language is rooted on protocols

henriklundahl17:11:11

Would it be possible to take the whole Google Maps API and put that as an extern?

dnolen18:11:57

@henriklundahl: you could try that but that doesn’t sound like a good idea to me

dnolen18:11:27

js->clj is so trivial for the longest time I refrained from including it

dnolen18:11:35

cases like this reaffirm that it was probably never a good idea

henriklundahl18:11:34

Ok, sure, but I'm just worried that other things suddenly start breaking...

dnolen18:11:54

I don’t see why

dnolen18:11:09

js->clj is a just convenience thing

dnolen18:11:27

you have so many better helpers for dealing with foreign data in ClojureScript and Closure I really don’t know why people bother

henriklundahl18:11:14

Ok, I guess there aren't many places in my code where I'm dealing with Google Maps objects and when I do I don't use any CLJS functions, except in this case.

henriklundahl18:11:28

So I guess I shouldn't worry.

grav18:11:05

@mfikes: thanks for your follow ups wrt re-defining a function! The solution with the ns-qualified var works great! And good work on the issue report simple_smile

mfikes18:11:26

@grav: simple_smile Looks like we are coming up on a year of having var. Interestingly, perhaps the first commit refers to shadowing https://github.com/clojure/clojurescript/commit/91153fa7d26f55cc466ac1d24184ba78bac7cf72

tony.kay18:11:19

I'm trying to pull an item from a set. The item in the set has metadata, but when I use get, it seems like get returns the lookup value I used, and not the item actually in the set...anyone have ideas?

dnolen18:11:59

@tony.kay: seems like you found a ClojureScript bug

dnolen18:11:10

that works in Clojure, file an issue in JIRA

tony.kay18:11:43

ok. will do

dnolen18:11:16

@tony.kay: something else to check

dnolen18:11:46

{(with-meta [1 2] {:foo true}) 3} in Clojure vs. ClojureScript

dnolen18:11:54

when using find

tony.kay18:11:08

(meta (get #{[1] [2] (with-meta [3] {:k 1})} [3])) returns nil for me

dnolen18:11:48

important to check Clojure behavior here

dnolen18:11:13

(yeah seems to work fine in Clojure)

dnolen18:11:33

so likely the underlying stuff in hash maps is what is wrong

dnolen18:11:38

since sets just re-use

mfikes18:11:29

Yeah, it works for a vector: (meta (get [[1] [2] (with-meta [3] {:k 1})] 2))

mfikes19:11:37

Maps themselves are fine: (meta (get {[1] [1] [2] [2] [3] (with-meta [3] {:k 1})} [3]))

roberto21:11:52

I’m trying to use goog.async.Debouncer http://google.github.io/closure-library/api/source/closure/goog/async/debouncer.js.src.html But when I do (:import goog.async.Debouncer) , I get a no such namespace exception.

thheller21:11:37

@roberto that file is pretty new, good chance it isn't in the closure release that is used by clojurescript

roberto22:11:07

ah, ok. Thank you.

jstew23:11:02

does clojurescript have an index-of function where I can get the position of an item in a list? In clojure proper, we call out to java, but best I can do it seems is convert the list to a js array first then use .indexOf on it.

noonian23:11:43

you could combine filter and map-indexed

jstew23:11:37

I ended up writing my own index-of just now that takes a collection and a predicate function to filter with.

jstew23:11:08

not perfect but works. Seems like something missing from the language, IMO.