Fork me on GitHub
#clojurescript
<
2018-03-20
>
quang05:03:01

newb question: Any reason it's resources/public and not just public ?

quang05:03:13

ok figured it out, i guess, figwheel requires it.

emil0r07:03:21

@quang Java allows you to package resources with you into a jar file. That's where the resources directory comes from. public is the default directory for things you want to be publicly accessible (through a web server for example)

smogg09:03:55

I'm trying to use cljsjs/react-beautiful-dnd in my project and the documentation mentioned I shall pass a function as component's children:

The React children of a Droppable must be a function that returns a ReactElement.

<Droppable droppableId="droppable-1">
  {(provided, snapshot) => ({
    /*...*/
  })}
</Droppable>;
How would that translate into ClojureScript?
(def droppable (r/adapt-react-class js/ReactBeautifulDnd.Droppable)

[droppable {:droppable-id "some-droppable"}
     (fn [provided snapshot]
       ...)]]
 ...
^^^ will complain about passing a function as children

smogg09:03:04

Ok, this is as easy as providing :children key in comp's props"

[ droppable {... :children (fn [x y] ...)}]

pesterhazy10:03:36

@smogg even easier [droppable (fn [x y] ...)]

pesterhazy10:03:00

oh I saw that you tried that

pesterhazy10:03:06

what's the error you're getting?

pesterhazy10:03:02

I don't know why that shouldn't work

Mikko Harju11:03:06

I found the most peculiar bug in Clojurescript/Figwheel/Fireplace… If I have npm-deps in my dev -build, every other evaluation takes something around 10 seconds. Has someone else experienced anything similar?

Mikko Harju11:03:40

It evals two forms, {:msg-name :repl-eval, :code "cljs.core._STAR_print_namespace_maps_STAR_ = true", :figwheel-version "0.5.15", :build-id "app", :callback-name "figwheel_callback_71846"} and then there is 10 seconds of pause before the actual form to be evaluated, for instance just (+ 1 1)

grounded_sage11:03:42

I have been away from Clojure for a while @mikko so I may be doing it wrong. But I literally have a minimal Boot setup with no figwheel and I'm trying to use React Native Web. Which requires npm-deps. I'm getting anywhere between 2-70 second builds.

Mikko Harju11:03:21

Hmmm, oh so it might be that the javascript-compilation step takes the extra time? I already checked that within FigwheelEnv:s (-evaluate) it takes the same amount of time for both of the forms, so the time is took between those calls

Mikko Harju11:03:42

Compilation taking extra time would actually make sense why this is happening

Mikko Harju11:03:56

Since it evaluates the compiled javascript form

grounded_sage11:03:28

I am assuming this is because it is going through Nashorn? I don't know. So much has changed in Clojure ecosystem.

Mikko Harju11:03:42

I’m not familiar with the compiler how it does its thing. The strange thing is that this is consistently fast every other eval, slow every other. If I cancel the evaluation midway when it’s slow, it’s slow until I eval it completely. Then the other invocation is fast again (the evaled form can be different, it does not matter here)

mfikes12:03:02

@mikko If you can catch the compiler in one of the 10-second pauses, using jps first to find the process ID, and then jstack during a pause to get a stack trace, that might help isolate what it is doing at the time.

mfikes12:03:17

@mikko There is a comment at the bottom of https://dev.clojure.org/jira/browse/CLJS-2339. If you learn more, perhaps open a new JIRA with that info.

smogg12:03:14

@pesterhazy That'd result in an error similar to: objects are not valid as a react child

rauh12:03:18

@smogg Have you tried [:> js/ReactBeatufiulDnd.Droppable {:roppable-id ".."} (fn ....)]

smogg12:03:09

the combination of :children key set along with returning a component using r/as-element from that function is the only thing that seems to be working

smogg12:03:33

[:> js/ReactBeautifulDnd.Draggable {:children
                                                       (fn [provided snapshot]
                                                         (r/as-element ...
...

pesterhazy12:03:24

@smogg think this must be an issue with reagent

pesterhazy12:03:35

OTOH i didn't know you could pass children using :children

jcr13:03:13

I'm reading https://code.thheller.com/blog/shadow-cljs/2017/11/10/js-dependencies-in-practice.html and am a bit confused. Is (:require ["thing" :as thing]) syntax a part of clojurescript itself or does shadow-cljs pre-process the source files?

thheller13:03:47

It is official CLJS syntax but the feature actually works reliably in shadow-cljs. :npm-deps of CLJS itself is still a bit wonky and unreliable.

jcr13:03:46

I see. Thanks!

grounded_sage13:03:58

What is this new symbol :>?

grounded_sage13:03:25

Ah I see it's Reagent specific.

juhoteperi13:03:42

:children property is same as providing list of children after props map

juhoteperi14:03:47

As mentioned by React docs, https://reactjs.org/docs/react-component.html#props, props.children is usually defined by providing children in JSX/or hiccup etc. but it can be provided in props map if not provided elsewhere

darwin14:03:37

just wondering if there is some cljs.pprint replacement which would allow me to limit max string length inside printed output, looked into fipp but didn’t see that option there…

mfikes14:03:17

@darwin FWIW, Fipp is extensible, so you could get away with defining your own visit-string. (I suppose you'd have to delegate back to the base implementation for all of the other IVisitor methods.)

Bravi15:03:19

hi everyone. is there an equivalent to this destructuring in cljs?

const destructure = ({ a, b, c, ...rest }) => console.log(rest);

Bravi15:03:40

basically that rest bit

Bravi15:03:54

I tried the following

(defn dest [{:keys [a b c & rest] }] ... )

Bravi15:03:58

but it doesn’t like it

alexmiller15:03:12

use sequential destructuring

alexmiller15:03:23

(defn dest [a b c & rest] ... )

alexmiller15:03:03

the {:keys ...} is associative/map destructuring for when your input is a map

Bravi15:03:41

yeah, I have a map as an input

Bravi15:03:48

just like in js I have an object

Bravi15:03:17

I guess there’s no equivalent

Bravi15:03:28

I couldn’t find it in any docs 😄

Rodin15:03:10

You could do it without destructuring: (defn dest [m] (println (dissoc m :a :b :c)))

Rodin15:03:29

Depending on the usecase.

Bravi15:03:14

yeah, but I was just wondering. I’m creating a little presentation on ClojureScript and I was just comparing a few js examples to Cljs implementations

pesterhazy15:03:19

yeah there's no function to "split" a map into a map containing :a :b :c and one containing only the rest

Bravi15:03:38

👍 thanks

pesterhazy15:03:42

IME in practice that need does come up sometimes but not that often

Bravi15:03:03

it does when you want to pass down the rest of the map to another component for example

Bravi15:03:41

but then again, in cljs you would structure things differently

pesterhazy15:03:44

right that's the use case I've had as well though often unknown keys are just ignored so it doesn't matter that much

Bravi15:03:21

I was just gonna say that functions (or components in this case) will only extract what they need

dnolen15:03:05

1.10.217 is available, we’re getting very close to the big release - please test

Mikko Harju15:03:34

All right, I’ll try that if I can 🙂

mfikes16:03:17

@mikko Cool. If you can in any way produce a minimal repro and file in JIRA, that would help immensely in resolving whatever is going on. I couldn't find a repro. See this for definition of "minimal": https://clojurescript.org/community/reporting-issues

Mikko Harju16:03:34

@mfikes All right, I’ll try..

mfikes16:03:52

Thanks... that would lead to the greatest chance of resolving it

Mikko Harju16:03:56

I’ll build me a version of cljs from master?

mfikes16:03:31

Yes, you should as described in the web page

mfikes16:03:16

Also @mikko if it makes it easier, even though the page doesn't mention it, minimal repros using the new cljs.main are also accepted

Mikko Harju16:03:56

OK, that is completely unknown territory to me. Maybe this would be the appropriate time to try that stuff out but 🙂

Geoffrey Gaillard17:03:56

Hi everybody ! I have a pretty big cljs app (900k in :advanced mode and gziped) and I'm trying to make it smaller. I have a bunch of pages like :page/home or :page/about and I'm routing with a multimethod like (defmethod get-view :page/home [] [:div.page#home]). IIRC, defmethods are not removed by the closure compiler dead code elimination. Is there an idiomatic way in the cljs world to dispatch to various pages/components while preserving the advantages of DCE ?

dnolen17:03:25

you want :modules

dnolen17:03:37

that’s our integration with Google Closure code splitting feature

scknkkrer18:03:05

Guys. Are there anyone who is familiar with cocos2d with clojurescript ?

scknkkrer18:03:41

Are there any mature Library for developing cocos2d with cljs ?

darwin18:03:59

just for record, here is a working solution to my problem above using fipp, needed a way how to pprint, but shorten long strings, thanks @mfikes: https://github.com/binaryage/dirac/blob/master/src/shared/dirac/shared/pprint.cljs

leontalbot19:03:23

Was sad to see that format fn was not implemented in cljs, then I found cuerdas.core/format! https://stackoverflow.com/a/49392549/1184248

jrbrodie7720:03:25

I just figwheel 0.5.15 moved a project from OS X to a windows machine and I'm getting a compilation error with a packaged called oops:Failed to compile build :client from ["src"] in 8.959 seconds. ---- Could not Analyze resources/public/js/oops/config.cljs ---- java.io.FileNotFoundException: Could not locate cuerdas/core__init.class or cuerdas/core.clj on classpath., compiling:(oops/helpers.clj:1:1) ---- Analysis Error : Please see resources/public/js/oops/config.cljs ---- Figwheel: initial compile failed - outputting temporary helper application to resources/public/js/client.js

darwin20:03:49

@jrbrodie77 are you using the latest version of cljs-oops 0.5.8?

dpsutton20:03:20

i mention just because its bitten me before. any chance you haven't committed recently added files? I've for sure pushed some broken builds before in the past.

jrbrodie7720:03:44

@darwin I'm using 0.5.8. I think that the exact package is a red herring. I just factored out oops and now I'm getting a similar error regarding parsley.

justinlee21:03:02

Is there anyway to destructure javascript objects? It’d be very handy when you have to pass a callback to a javascript library.

john21:03:42

(let [{:keys [k1 k2]} (js->clj js-obj :keywordize-keys true)] ...

john21:03:44

might work

kvlt21:03:17

Is there a way to return a value from a go block in cljs? I have something similar to this:

(go
  (let [channel (http/call with-some-params)
        data (:some-key (<! channel))]
    data))
Obviously this returns a channel. However. I'd like to have block and return a value

justinlee21:03:29

@john thanks yea that does work but that’s precisely the thing I was hoping to avoid 🙂 if i’m going to do that it’s easier to just do (.-k1 js-obj)

john21:03:50

oh, js-obj is already a reserved word for a function

justinlee21:03:06

oh well yea but you know what i mean

john21:03:37

Well, destructuring isn't always the fastest method

justinlee21:03:40

@petr you can’t really block in javascript because it is single threaded. i don’t even think the blocking take operators are is implemented

justinlee21:03:52

i don’t care about speed

kvlt21:03:37

Yeah, I noticed the <!! operator was missing

john21:03:44

I mean programming-wise. Destructuring usually makes code more succinct. In your example, maybe not.

justinlee21:03:28

true. the syntax for destructuring maps is just about the only thing I don’t like in cljs as compared to javascript

justinlee21:03:11

@petr you just have to deal with the fact that i/o is async in javascript and therefore is async in clojurescript

darwin21:03:26

but it is dangerous ^

justinlee21:03:26

danger is my middle name

justinlee21:03:23

that’s completely amazing although i don’t really understand it

darwin21:03:50

read clojurescript compiler source code 🙂 how get and get-in are implemented 🙂

john21:03:16

cool kids don't use js objects 😉

justinlee21:03:49

unfortunately there are like 500,000 very uncool libraries on npm

🤓 4
kvlt21:03:05

That few?

john21:03:57

There are a lot of ways to tweak cljs so that you can essentially just easily write raw js in lisp. By not building those "easy" paths down the road of mutability, we are helping ourselves avoid pain through conventions, moreso than what is and isn't possible. So like @darwin said, careful making mutable objects that look like the good stuff when they're not.

john21:03:38

But if you're feeling naughty, check out extending string too 😉

justinlee21:03:17

I’m a simpleton hacker who has never really understood the appeal of immutability in a single-threaded environment except as a performance enhancement for deep comparisons, but I don’t need to start a debate that I certainly can’t win.

john21:03:47

well, 1) there's still "concurrency" and, 2) when threadish things come to JS, we will be here waiting 🙂

john21:03:40

And 3) it's more about the mental model that immutability provides, than just the concurrency guarantees, which my mind is more used to now, so I'd prefer it anywhere on any host

justinlee21:03:44

oh okay i get the thing that darwin posted. so does detructuring use that same protocol?

JJ21:03:00

@lee.justin.m it decomplects time and value

JJ21:03:56

which is also useful in single-threaded enviroments

justinlee21:03:11

@devicesfor I probably don’t really understand what that means. The standard model in reagent, for example, is to mutate a big ol’ state atom.

john21:03:42

ILookup is a protocol for finding things in objects, like things in maps. Maps implement -lookup which is what destructuring uses to pull things out of maps.

john21:03:25

When you do a get on a map, underneath it is calling -lookup

justinlee21:03:56

yea i think i get that. it was this part that i wasn’t sure about before: which is what destructuring uses to pull things out of maps

justinlee21:03:13

obiously there’s some code in the bowels of the cljs compiler that implements that

JJ21:03:58

@lee.justin.m immutable data removes complexity, since you can't edit it, it makes things simpler, mutating creates lots of problems

john21:03:03

destructuring is just using the same tools you use to get things out of maps

john21:03:34

and as long as you implement a similar interface, it'll blindly call the methods it expects to exist

justinlee21:03:50

@devicesfor Yea people say that a lot but I can’t think of a single instance of web code I’ve ever written that would have been helped by it. I’m sure you’re right. It’s just that I’m a concrete thinker and need concrete examples or I don’t understand it. Plus the “immutability” of the state atom seems sort of hollow give that you are actually mutating it all the time. I’m certainly not against immutability, it’s just that its much easier to understand how it can save your bacon in a multithreaded environment.

justinlee21:03:16

@clojurians-slack cool thanks. i probably won’t mess with that since it sounds like a Bad Idea, but I like that it is possible

john21:03:24

eh, it's not really true. A single javascript execution context is single threaded. And a only a single thing will be editing an object at time. But in js, if you don't protect your data, then other processes can still clobber it.

john21:03:35

and under the hood, the browser is employing many threads and many of your particular js contexts of execution, while not necessarily multi threaded, need not actually process in order.

john21:03:52

a lot can go wrong

john21:03:15

but yea, run to completion semantics in js eliminates large classes of errors that we don't have to worry about

justinlee21:03:42

i agree with all that, particularly the last part. 🙂

john21:03:48

gotta run, ttyal

justinlee22:03:46

@devicesfor thanks that’s a good talk. i was familiar with the flux performance enhancement thing (which is what I was referring to above). The intervening mutator example right at the beginning is pretty compelling. Definitely easier to reason about a program when variables are referentially transparent or have an @ before them to let you know they might not be.

john22:03:37

@ is a "killer feature" 😂

john22:03:10

it's a very succinct interface between two asynchronous contexts

john22:03:44

even if the two contexts aren't asynchronous, by building the second call to deref on every place you might mutate, it allows you to do that easy separation of contexts.

john22:03:05

what happens on the other side of that -deref call could be on the other side of the world, doesn't matter.

justinlee23:03:56

i just learned about how deref is used in clojure promises, futures, vars and refs, but i’ve only seen it used in cljs with atoms. maybe there are other cool things you can do with it?

justinlee23:03:00

one of my problems is that the history of cljs is clojure people making clojurescript but i went straight from javascript to cljs. that’s a disadvantage when reading docs sometimes

john23:03:36

clj is like a hygienic transformation environment where potentially unhygienic, mutable transformations are logically partitioned off behind a wall of deferrability. Some of that whole abstraction does pay dividends in js land. David nolen proved that with his "react faster than react" thing a few years ago.

john23:03:12

But really, how long do you think js land is going to stay this way, without shared memory and threads?

john23:03:19

The only reason everyone isn't using web workers is because the abstraction is too hard for beginners to solve simple concurrent problems.

dnolen23:03:36

@lee.justin.m well fwiw, I was doing JavaScript for 6 years before I started contributing to ClojureScript - there’s a learning curve for sure - but honestly I think from one perspective, I think the barrier of entry for a JS programmer is lower than for Java programmer

dnolen23:03:39

one problem is I started doing JS back when it was pretty hard, IE 6 was still important

dnolen23:03:58

so a lot of the new stuff that JS stuff people came up with just didn’t make any sense to me

dnolen23:03:06

still doesn’t 🙂

justinlee23:03:08

@dnolen oh yea i’m not whining. i tried to circumscribe my statement to the very limited “disadvantage when reading docs sometimes”.

justinlee23:03:20

in particular clojuredocs is clojure-focused

dnolen23:03:57

sure but it’s an odd thing to say in the sense that every community is navel-gazing

dnolen23:03:03

JavaScript stuff is JavaScript focused

justinlee23:03:04

and some of the “deeper” books are clojure-focused too and i’m too lazy to try to sort through what’s useful for cljs and what is really clojure focsed

dnolen23:03:06

right that’s interesting - but I personally feel the gap between CLJS and Clojure is pretty boring

dnolen23:03:26

enough that the most important things about Clojure carry over to ClojureScript and vice versa

dnolen23:03:44

there’s a reason ClojureScript bootstrap wasn’t that hard

justinlee23:03:37

maybe you’re just better at this than me. i feel like i run into stuff all the time that is clojure specific. there are a number of libraries and concepts that are described in the context of threads, for instance

justinlee23:03:19

it’s not a big deal. it was just an offhand comment. really learning clojurescript has been a delight.

john23:03:51

@dnolen you're not a good example of a js dev coming to cljs 🙂

dnolen23:03:16

well it’s just my own perspective and that’s problematic for lot of reasons - still I think the neat thing about CLJS -> CLJ (which is a new phenomenon)

dnolen23:03:31

is that it’s like whoa - I can upgrade from single-threaded semantics to multi-core

dnolen23:03:41

and it’s not a hard transition

john23:03:16

yeah, I think that's super interesting. @lee.justin.m have you tried clojure, as a result of getting into clojurescript?

justinlee23:03:31

not yet. my backend is just a bunch of javascript glue between an rdbms, elastic search, and some batch processing junk that runs on express. it doesn’t really cause me as much pain as the frontend so i went front end first.

justinlee23:03:15

also in a previously life i dealt with massive concurrency in c++ and it was a nightmare that we eventually wrote in an async style. with node, you’re there already so i have a degree of comfort with that style

justinlee23:03:27

where concurrency = multithreading