Fork me on GitHub
#clojurescript
<
2016-12-18
>
grounded_sage01:12:11

I'm getting a weird error that I can't seem to shake.

clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to resolve symbol: defstyle in this context, compiling:(vbn/web.cljc:12:1)
             java.lang.RuntimeException: Unable to resolve symbol: defstyle in this context
. Here is the gist of the file. https://gist.github.com/CommonCreative/0ed06d8ddfd5dbde01d14b2e335678b6 I am using Boot too if this changes anything.

futuro02:12:36

Anyone know of a high-level io library that's pure cljs?

hlolli03:12:25

@futuro try using nodejs fs, with #lumo for example. No/few other ways I know of.

futuro04:12:35

@hlolli yeah, I'm currently working on a cljs version of tools.nrepl, so I'm looking into ways to make it vm agnostic

johanatan05:12:33

hi, does anyone have a recommendation for lein or boot for starting new node.js (NPM module) ClojureScript projects? and if so, any example or template I can follow?

chrisoakman05:12:48

@johanatan Is your intent to use CLJS to generate a JS file and then publish that JS file to npm? Or are you creating a library that would be useful to use from CLJS?

johanatan05:12:59

@chrisoakman the first-order goal is to do the former although the latter is a secondary concern. FWIW, the current lein-based version of my library is consumable via both languages

johanatan05:12:37

@chrisoakman I am looking to update it as the project was started almost 2 years ago and a lot has changed in the CLJS world since then

johanatan05:12:10

it's also a bit fragile from a maintenance standpoint (I forget specifics at this point) so bringing it up to date is the first step to remedy that

johanatan05:12:30

here it is if you want to take a look at it: https://github.com/johanatan/speako

chrisoakman05:12:35

Clojars is probably the best place for a CLJS library. Easiest to consume for CLJS users.

martinklepsch05:12:22

Never tried but maybe you could use none, filter out your files and turn it into a Closure module.

martinklepsch05:12:57

I'm not sure if Babel and other tools understand that format but at least it should be easy to incorporate into CLJS while still being regular JS

martinklepsch05:12:41

probably on the JS side it would get hard to make sure dependencies are met though

johanatan05:12:57

my primary concern here is merely starting a state-of-the-CLJS-art Node.js [library] project publishable to NPM. the CLJS use of it is secondary (and not important at first)

johanatan05:12:12

I just imagined that there would be some sort of template for this sort of thing for at least one of: {boot, lein}

johanatan05:12:21

this library only exports a single function. the difference between using it from CLJS or JS is to merely call cljs->js on the inputs or not.

chrisoakman05:12:17

I don't know much about lein templates, but sounds like you just need to produce a single JS file that is consumable by node.js and then make sure it does module.exports() with what you want.

johanatan05:12:33

@chrisoakman yes, that is exactly what i'm doing

johanatan05:12:54

but that isn't what I'm asking on here how to do

chrisoakman05:12:43

The [atom-parinfer](https://github.com/oakmac/atom-parinfer) plugin might be helpful. It is written in CLJS and publishes a JS library to apm (basically the same thing as npm; just for atom packages).

johanatan05:12:50

So, there's no std template for either boot or lein for starting a new node.js project?

johanatan05:12:09

Seems like one of the very first things that people would want to do with ClojureScript.

chrisoakman05:12:43

That may exist; I wouldn't know.

johanatan05:12:45

ahh, a bit of Googling turns up a few things but none have been touched in the last year (which is barely better than the 2 year-age of my hand-rolled-from-a-few-blogs-somewhere solution).

johanatan05:12:31

And, it seems "hand-roll-[piecemeal]-from-a-few-blogs-somewhere" is a sort of modus operandi about many CLJS things. 🙂

chrisoakman05:12:43

I suppose that's one way to look at it.

chrisoakman05:12:16

Feel free to copy the atom-parinfer project.clj as a template: https://github.com/oakmac/atom-parinfer/blob/master/project.clj

chrisoakman05:12:24

That should get you 99% of the way there.

johanatan05:12:51

🙂 yea, i will try. I recently did the same with a different project and it got me 95% of the way there but the remaining 5% was a show stopper.

johanatan05:12:44

@chrisoakman anyway, thanks for the input.

johanatan05:12:32

ahh, I remember now what the show-stopper was on my previous attempt: https://github.com/lbradstreet/instaparse-cljs/issues/20

johanatan05:12:16

It seems after updating to the latest CLJS and such and updating the project template/compilation, that bug/mis-compile or whatever it is was exposed in instaparse.

johanatan05:12:41

But the instaparse maintainer doesn't think it is an instaparse bug (and he couldn't reproduce it).

aengelberg09:12:12

Hey @johanatan, I never got around to investigating your bug after you followed up with the more concrete issue; I'll take a look tomorrow

crankyadmin16:12:05

Hi, const {block} = this.props; (block.getEntityAt(0)) —> snip… (aget props “block”) (.getEntityAt block 0) snip… right?

kishanov16:12:53

Is there any way to make pprint to print function definition instead of string representation of JavaScript function? i.e. for

(pp/pprint {:my-fn (fn [x] (+ 2 x))})
to output the original data structure instead of
{:my-fn #object[Function "function (x){
return ((2) + x);
}”}}

jrheard17:12:17

@crankyadmin i haven’t done regular JS in a while, but one thing that seems different between the two code snippets you’ve given is that on the left, something seems to be assigned to the name “block”, whereas on the right that doesn’t happen

jrheard17:12:44

maybe a (let) would be helpful, so you can assign (aget props “block”) the name block

jrheard17:12:26

if that’s not what you’re looking for, more info about what you’re trying to do and what you’re seeing would be helpful 🙂

crankyadmin17:12:41

@jrheard Its cool. I cheated. (js->clj (.valueOf block 0) :keywordize-keys true)

crankyadmin17:12:17

Sorry if I wasn’t clear. I did have a let in my code already. I cut it right down to the bare min for pasting in here.

jrheard17:12:22

aha, gotcha

johanatan19:12:59

@aengelberg: ahh, awesome! Thanks!

kzeidler20:12:01

I'm afraid there's a critical piece of information I'm missing in regards to the repl

raaon20:12:14

re, om/next -- i am thinking the answer to this question might solidify some things i'm missing. why does om/next need to deal w/ remotes? couldn't remoting have been left out entirely, leaving the user to make async calls and merge the state back into the reconciler out-of-band. what am i missing? what can/is om/next doing for us by being the middle-man for :remotes?

kzeidler20:12:45

(I'm using Leiningen repl currently.) The REPL starts in some generic "cljs.user" namespace that doesn't seem to be populated with any user-defined functions. I can switch to particular namespaces, but those namespaces seem not to have loaded clojure? Alternately, I can require those namespaces from the cljs.user namespace, but that doesn't appear to make those definitions available in cljs.user.

kzeidler20:12:50

What am I doing wrong ?

kzeidler20:12:14

The takeaway I'm getting from googling this issue is that the correct way to load specific namespaces into the REPL might depend a little bit on your clojurescript version

borkdude21:12:31

What would be a performant translation of this JS to cljs:

function addScrollListener() {
    var timeout;
    window.addEventListener('scroll',function(e) {
      if (timeout) {
        clearTimeout(timeout);
      }
      timeout = setTimeout(recordScroll, 1000);
    });
  };
Does using an atom for timeout involve too much overhead, maybe a volatile? What it does: it records the scroll position when the user has stopped scrolling for more than a second

anmonteiro21:12:17

@borkdude I think you can translate it directly with a let

anmonteiro21:12:57

the variable would be closed over by the callback function so the JS semantics would be maintained

borkdude21:12:22

@anmonteiro you can’t mutate let bindings

anmonteiro21:12:42

oh right I didn't see that part

borkdude21:12:15

since this is triggered on every scroll event it better be fast as possible 🙂

anmonteiro21:12:40

you can probably use a volatile!, though I don't think it's any faster than an atom

anmonteiro21:12:59

maybe just less memory because it implements less protocols?

borkdude21:12:01

@anmonteiro an atom does some extra work, like calling watchers right?

anmonteiro21:12:11

not even sure that's correct

anmonteiro21:12:27

yes, that's right

anmonteiro21:12:31

volatiles have no watchers

borkdude21:12:25

also no validators

borkdude21:12:24

So roughly:

(defn add-scroll-listener []
  (let [timeout (volatile! nil)]
    (.addEventListener js/window “scroll”
      (fn [e] 
        (when-let [t @timeout] (js/clearTimeout t))
        (vreset! timeout (js/setTimeout recordScroll 1000))))))

mfikes21:12:01

It might be interesting to see if something horrific like this flys: (let [x 1] (js* "x=2") x)

mfikes21:12:22

(defn add-scroll-listener []
  (let [timeout nil]
    (.addEventListener js/window "scroll"
      (fn [e]
        (when timeout (js/clearTimeout timeout))
        (let [x (js/setTimeout recordScroll 1000)]
          (js* “timeout=x”))))))

borkdude21:12:46

This is extremely hacky but it worked:

(defn add-scroll-listener []
  (js* "var timeout")
  (.addEventListener js/window "scroll"
  	(fn [e] 
      (when (js* "timeout") (js/clearTimeout (js* "timeout")))
      (js* "timeout =" (js/setTimeout record-scroll 1000)))))

mfikes21:12:01

Frankencode 🙂

borkdude21:12:15

oh hey @mfikes I see you were also hacking with js* 🙂

mfikes21:12:55

There might be some cljs.core.truth_ call you can eliminate too.

borkdude21:12:22

this is extremely useful for testing these kinds of things: http://app.klipse.tech/

anmonteiro21:12:47

@borkdude planck -v or lumo -v will also print the generated JS source

mfikes21:12:21

I wonder if (when ^boolean (js* “timeout”) … is semantically correct, but it gets rid of a call to truth_

borkdude21:12:22

The nice thing about Klipse is that I can test also if the scrolling thing worked 🙂

anmonteiro21:12:32

oh that's right

anmonteiro21:12:47

but it makes me think if that should be the default behavior

anmonteiro21:12:03

I would rather if it ran my JS input in a "sandbox"

borkdude22:12:24

@mfikes you’re right, it eliminated the call 🙂

mfikes22:12:28

Hah… yeah, it looks practically like your original JS now.

jrheard22:12:35

late to the party - in a hot loop, i’ve definitely noticed that getting rid of truth_ makes a noticeable difference, i got rid of 7% of the work one of my loops was doing by adding ^boolean in the right places per above (this was months ago, actual specifics/details escape my memory)

jrheard22:12:24

+1 to using klipse for getting the actual syntax right, will also try -v in planck/lumo

borkdude22:12:16

I’m wondering why ^boolean (js* “timeout”) gets rid of truth_ but ^boolean timeout won’t, in this code:

(defn action []
  (println "foo"))

(defn add-scroll-listener []
  (let [timeout nil]
    (.addEventListener js/window "scroll"
      (fn [e] 
        (when ^boolean (js* "timeout") (js/clearTimeout timeout))
        (js* "timeout=" (js/setTimeout action 1000))))))

(add-scroll-listener)

borkdude22:12:30

(btw “scroll” doesn’t work well in Klipse since there is nothing to scroll, so for testing I put it to “resize”)

borkdude22:12:51

putting the type hint in the let worked btw

mfikes22:12:19

@borkdude: if that ultimately fails under :advanced perhaps using set! on a top-level def would work, assuming only one scroll listener is started up

borkdude22:12:47

@mfikes Actually, I was just wondering how to accomplish this, but I’m not going to use it. If I would write it in cljs I’d probably go for volatile, because that just uses a field in an object, which should be fast enough.

borkdude22:12:57

(hopefully, I’ll see when the need arises)

stbgz23:12:37

hey all am I missing something when doing this

(js->clj “{‘a’:1”} :keyworddize-keys true)
outputs "{'a' : 1}” 

stbgz23:12:12

I was expecting the clj dict with a as a key. I am pretty sure I’ve seen that working somewhere

teaforthecat23:12:13

wow, that is related to the previous conversation kind of. does this work?

(js->clj (js* "{'a':1}") :keyworddize-keys true)

stbgz23:12:11

yeap that works..

stbgz23:12:29

thanks moving between js cljs sometimes makes me dizzy

stbgz23:12:08

(js->clj (.parse js/JSON "{\"a\":1}") :keywordize-keys true)

teaforthecat23:12:28

funny, I wish I could tell you where js* is defined, but I can’t find it

teaforthecat23:12:00

if it is json, then yeah, that’s better

stbgz23:12:55

no worries thanks js->cljs get me sometimes