Fork me on GitHub
#clojurescript
<
2016-08-02
>
mathpunk00:08:13

I’m newly a JS dev, and I would like to write scripts (planck), UI (rum/figwheel), and node (figwheel?). But I when I was tinkering a couple years ago I was pretty JVM focused.

mathpunk00:08:48

Thanks, @anmonteiro, I didn’t realize cljs.spec was a thing

johanatan01:08:27

anybody here using a CSS preprocessor with lein / figwheel ? (I am leaning towards stylus but SASS is second pick).

johanatan01:08:44

am curious how to setup/integrate with both cljsbuild and figwheel

akiroz01:08:26

I'm using SASS you can check out this guide: https://github.com/bhauman/lein-figwheel/wiki/SASS-watcher I didn't follow it because I thought it was a bit messy, instead I did :figwheel {:css-dirs "resources/public/css"} to watch CSS files in that directory then ran a seperate instance of sass --watch ...

bhauman01:08:19

Yes this is the recommended way

michael.heuberger03:08:26

hello guys, is there a public registry for clojurescript libraries similar to http://npmjs.com?

akiroz04:08:16

It's shared with clojure libs on clojars

michael.heuberger04:08:13

doesnt appear on top when you google for “clojurescript libraries” 😕

michael.heuberger04:08:38

but yes, thanks, was looking for that

akiroz04:08:30

well, the distinction isn't made that clear between clj and cljs libs because both are packaged in JARs and some libs work in both clj and cljs.

skeuomorf04:08:23

What's the proper way to use core.async from clojurescript when using leiningen? i.e. Which package to depend on? And do I need to do anything different from what I'd do when using clojure to require it?

akiroz04:08:31

It's the same core.async package, you require cljs.core.async but keep in mind that macros in CLJS needs to be explicitly imported.

skeuomorf04:08:07

@akiroz: ah, removed the go macro from my refer, thanks!

pbiggar07:08:38

@si14: any idea? Got a warning that I'm totally fine with, and very eager to kill it 🙂

krchia08:08:21

i’m not sure if the community at large could use this, but i have a lot of code samples where i’ve basically translated js stuff into cljs versions that could be good examples; it was a lot of pain for me to learn like this and i - think - it might be helpful for others?

krchia08:08:36

it’s definitely not idiomatic code, but it is the same output for both js and cljs versions

si1409:08:59

@pbiggar: as far as I know, it's impossible :(

urbanslug09:08:09

Should the cljs repl work with emacs out of the box after installing cider?

dominicm10:08:30

@urbanslug: I think you need figwheel / boot-cljs-repl in your project.

adamw10:08:04

folks; if I use boot as my build framework with (cljs-repl), it tells me sth like:

nREPL server started on port 62683 on host 127.0.0.1 - 
Adding :require adzerk.boot-cljs-repl to index.html.cljs.edn...
However if I connect to that REPL using intelllij cursive, and try to load a CLJS file it tells me it can't load ClojureScript files into a Clojure repl. Is that a cursive issue or am I doing something wrong?

martinklepsch10:08:40

@adamw you need to call (start-repl) to get into a cljs repl

urbanslug10:08:04

hmmm not using figwheel in the project yet but migrating to it.

adamw10:08:13

@martinklepsch: ok, thanks. so I ran that and I got

<< started Weasel server on ws://127.0.0.1:62807 >>
<< waiting for client to connect ... Connection is 
Writing boot_cljs_repl.cljs...
but cursive still refuses to recognise it as a cljs repl; and I can't connect to 62807. Guess I need to use a browser/weasel setup not intellij

urbanslug10:08:17

Seems to work out of the box with emacs live and spacemacs

dominicm10:08:02

Oh, you do have a cljs repl to connect to then. Not sure about it if it's an emacs problem.

urbanslug10:08:41

@dominicm: So I should run a repl from the terminal and have emacs connect to that?

urbanslug10:08:58

Yeah not an emacs problem I think I just don’t have something in my cider configs

dominicm11:08:14

@urbanslug: I don't use emacs/cider, so I really don't know.

martinklepsch11:08:30

@adamw the websocket port is not meant to be connected to. You could try doing the same from a terminal REPL session to diagnose if the issue is w/ cursive or with your overall setup

skeuomorf11:08:20

How does one parse JSON properly in CLJS?

skeuomorf11:08:05

I've used transit's read but I don't know what's the proper way to traverse the returned value.

darwin11:08:19

@skeuomorf: google closure library has tools for working with JSON, that would be first thing I would use, if only JSON parsing is needed: https://github.com/google/closure-library/blob/master/closure/goog/json/json.js

skeuomorf11:08:37

@darwin Cool cool, gonna check that out. Thanks 🙂

darwin11:08:52

the return value is normal js object, so you can use JS interop to work with it, or you can convert it to cljs with js->clj function (but that is not always the right choice depending on your needs)

darwin11:08:17

namely js->clj can have poor perfomance for huge data, and can choke on some “weird” javascript objects, e.g. circular references

darwin11:08:32

btw. many cljs.core functions recognise javascript arrays and can use them as sequences interchangeably, e.g. (map f js-array) will work, f will be called for each element of the array. This way I believe you can write some traversing code with cljs.core functions and resort to JS interop only in leaves.

darwin11:08:00

and one last note: if you end up with cljs data structure (e.g. via transit’s read or by calling js->clj), you can use clojure.walk for traversing the structure, or even clojure.zip

skeuomorf11:08:28

All these methods though will have me traverse the whole response and doing idx+1 to get the value that I want, right? i.e. I can't get a JS object literal -> Map with keywordized strings

darwin11:08:30

not sure if I understand, js->clj supports keywordizing keys

skeuomorf12:08:51

ah, nvm, I thought :keywordize-keys was the default

skeuomorf12:08:00

Thanks for working on devtools BTW 🙂

jaemk15:08:32

Anyone have experience setting up figwheel to be accessible to other machines on the local network? I've tried all the figwheel client-side settings: using the client's connected host :websocket-host :js-client-host, explicitly defining the host-name :websocket-host "myhostsname", overriding the websocket-url :websocket-url "". All of these things correctly modify the websocket-url in figwheel/connect.cljs file where the client websocket is started, but my clients always seem to ignore this and try to connect to ''. Am I missing something?

bodie16:08:34

@spinningtopsofdoom: thanks again for the heads-up for the Slack.

spinningtopsofdoom16:08:59

Glad I could help you out 🙂

spinningtopsofdoom16:08:46

@jaemk: You could set up a socket repl with figwheel then connect to it with tubular (https://github.com/mfikes/tubular)

jaemk16:08:11

@spinningtopsofdoom: Thanks for the suggestion. My issue is the browser isn't connecting to figwheel's 'reload socket'. I can see in the compiled js that the websocket url is correct (pointing to the correct host), but the browser always tries to connect to localhost instead.

spinningtopsofdoom16:08:51

Ah I just read the first line, ooops. The modifications to the host show up in figwheel/connect.cljs and the complied JavaScript, correct?

jaemk16:08:54

Yes, but the browser still tries connecting to ... instead of the url that's in figwheel/connect.cljs

spinningtopsofdoom16:08:15

I think I found it look at https://github.com/bhauman/lein-figwheel/blob/bb32c895040413159ea7d00556b3ec2cf4a0aed9/support/src/figwheel/client.cljs#L293. It uses the location.host of the browser to connect if localhost isn't specified. So you'll have to have the url have http://myhostsname/

jaemk16:08:01

Shouldn't that be overridden by the options I'm providing though? https://github.com/bhauman/lein-figwheel/blob/bb32c895040413159ea7d00556b3ec2cf4a0aed9/support/src/figwheel/client.cljs#L365 . The complied figwheel.client.connect.js has the following figwheel.client.start.call(null,new cljs.core.PersistentArrayMap(null, 2, [new cljs.core.Keyword(null,"build-id","build-id",1642831089),"app",new cljs.core.Keyword(null,"websocket-url","websocket-url",-490444938),""], null));

spinningtopsofdoom17:08:37

Yep I see you're correct, hmmmm. Do you know where in the compiled JavaScript ws//localhost.... is located?

jannis19:08:17

Hi! For some reason I'm having trouble with this: In a macro I want to generate a list expression for ClojureScript and in there is a function call that I want to be evaluated in ClojureScript. So something like ({:foo (my.cljs/fun 1 2)} {:bar :baz}). So as far as ClojureScript is concerned, the outer (...) should remain a list (and not be treated like a function call) and the inner function call should be called and replaced with its result. Any ideas how I do that?

jannis19:08:14

@darwin: Of course, that works. 🙂 I had list there before but something else wasn't happy about it. Probably my tests being too strict about the generated syntax.

honzabrecka20:08:08

Hi, is there any way how to use and dynamically with apply?

anmonteiro20:08:50

@honzabrecka: and is a macro so you’ll need to write a macro that does that. something like:

(defmacro apply-and [& body]
  `(and ~@body))
untested

val_waeselynck20:08:03

@anmonteiro: that's essentially the same thing as and 🙂

anmonteiro20:08:24

wow that is indeed

honzabrecka20:08:45

@anmonteiro: Thanks! Without & before body argument it works exactly as I wanted.

darwin20:08:01

I thought some cljs.core things are both macros and functions, and being one of them

anmonteiro20:08:08

that would be the fix

val_waeselynck20:08:12

@honzabrecka: (every? identity coll) does what you want if you only care about truthyness

anmonteiro20:08:33

@darwin: I don’t think that’s the case for and

honzabrecka20:08:20

@darwin: +, -, … macro and fn at the same time, and, or macro only

darwin20:08:34

ok, thanks

jannis21:08:55

@darwin: What if I need to generate ({:foo (my.cljs/fun 1 2)} {:bar :baz}) exactly like that, without the list?

jannis21:08:45

Is there some way to generate (...) without ClojureScript thinking it's a function call?

darwin21:08:58

your problem is not in the macro, I guess, but in the way where/how you expand it

darwin21:08:17

can you give me usage example?

jannis21:08:24

The code that generates this is pretty complex. What I want to generate is an Om Next query expression, so something like [({:user (om/get-query User)} {:id ?user-id})]. Sadly, Om Next expects parameterized queries to be (<query> <param map>) not (list <query> <param map>).

darwin21:08:39

so it means, that the code you are normally writing by hand gets quoted by some other macro, I would suppose

darwin21:08:13

so your own “inner” macro can simply generate (…) because it gets quoted by other macro expansion

jannis21:08:11

Doesn't that pass (<query> <param map>) up to ClojureScript, which will then think (...) is a function call instead of a list?

jannis21:08:43

Because it's evaluating the generated code?

darwin21:08:34

consider (outer-macro (my-macro (…))), my-macro can produce unquoted code, if outer-macro takes it and quotes it, cljs will evaluate the result after all macros were expanded

darwin21:08:08

I think something like this is going on (I’m not familiar with om-next)

darwin21:08:27

otherwise you could not write such unquoted code directly by hand in the first place

jannis21:08:18

@darwin: Is it possible to generate backticks?

jannis21:08:05

I know, that's probably a question that makes no sense.

darwin21:08:08

not sure, you can generate (quote (…)) which is equivalent to ‘(…)

jannis21:08:59

This is what I'm generating for ClojureScript at the moment: https://gist.github.com/Jannis/9c0e8efc9c6fc71547f0cc26ec3b06ce

jannis21:08:01

The problem is: ClojureScript thinks the ({:user ...} ...) is a function call and tries to evaluate it. I can put list in there and it receives it fine but Om Next isn't happy. I somehow need to quote the ()s but still allow CLJS to evaluate their content.

darwin21:08:32

what if you write that code by hand?

darwin21:08:42

does it have the same problem?

jannis21:08:21

Well, if I write it by hand - in CLJS -, I'd backtick quote it so it treats () as a list.

darwin21:08:47

why backtick? why not simply quote?

jannis21:08:04

Because the (om.next/get-query ...) needs to be evaluated/called in CLJS.

jannis21:08:12

If quote the entire thing that's not going to happen.

darwin21:08:03

and if you backtick whole thing it is also not going to happen

darwin21:08:43

please show me two pieces of code, in that gist, hand-written code and code produced by your macro

darwin21:08:57

I assume they will differ with quotes and backticks at various places

darwin21:08:13

but from your description I don’t understand where exactly

jannis21:08:10

In hand-written code I'd do <backtick>[({:user ~(om.next/get-query User)} ...)]

darwin21:08:32

and here we go, that tilda is important there

jannis21:08:41

With unquoting to evaluate the function call. Or maybe even <backtick>[(~{:user ...} ...)]

darwin21:08:45

you are breaking out of syntax-quote to call the function

jannis21:08:20

Now, that's something I can't easily do in code that I generate in Clojure for ClojureScript, right?

anmonteiro21:08:34

@jannis: FWIW, syntax-quoting is nestable

anmonteiro21:08:55

(defmacro foo [bar]
  `(identity `({:user ~~bar})))
boot.user=> (def x 42)
#'boot.user/x
boot.user=> (foo x)
({:user 42})

jannis21:08:25

@anmonteiro: I've been thinking about whether I can double-quote there. I didn't know how though. I'll give it a shot.

anmonteiro21:08:49

@jannis: double-quote and double-unquote :) ~~ looks funky

darwin21:08:55

this is not about “trying”, you should understand “why” 🙂

darwin21:08:33

I think the question boils down to: do you know the value of that tilda-sub-expression at compile time? if yes, why not simply generating that data as quoted thing

anmonteiro21:08:00

it has to be done at runtime

darwin21:08:09

(defmacro my-macro [] `(quote [(the-result-of-tilda-subexpr …)]))

anmonteiro21:08:22

it’s the result of CLJS evaluation

anmonteiro21:08:16

@jannis: you can always avoid the double-quoting thing by calling (list foo)

darwin21:08:46

there must be some other “outer” macro in play, because then I don’t understand why building the data via (vector (list ((subexpr-call) …)) wouldn’t work

darwin21:08:06

you said that Om expected () and not list

anmonteiro21:08:50

it does expect a list after the vector

jannis21:08:12

@anmonteiro: (defmacro foo [] (list :foo :bar)) - would that return a list to ClojureScript or an expression where it tries to call :foo?

anmonteiro21:08:26

expression to be evaluated

anmonteiro21:08:45

I meant

(defmacro foo []
  `(list :foo :bar))

jannis21:08:59

Right. That's what @darwin suggested earlier. For some reason Om Next wasn't happy with it, thinking (list :foo :bar) is a mutation, not a query (at least @anmonteiro knows what these terms mean ;))

anmonteiro22:08:00

could it be a bug in some other part of the app?

anmonteiro22:08:17

it really does look like a valid thing to me

jannis22:08:45

I guess it has to be...

jannis22:08:55

I'll try with recharged batteries tomorrow 🙂

darwin22:08:14

@jannis: you could create a minimal repro case project and I could look into that.

anmonteiro22:08:17

feel free to ping me if you’re still stuck

jannis22:08:15

@darwin: I'd do that right away if "minimal" didn't involve quite a few things in this case. Thanks 🙂

darwin22:08:42

try to do it as minimal as possible 🙂

darwin22:08:47

bye for now

jannis22:08:07

Good night