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.

chrisoakman05:12:10

Anytime šŸ™‚

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