Fork me on GitHub
#clojurescript
<
2016-09-01
>
jao00:09:06

hello. i'm getting an error compiling my project with 1.9.227.... "Wrong number of args (1) passed to: nodes/ranges at line 25 target/cljsbuild-compiler-2/clojure/core/rrb_vector/trees.cljs". things work fine with 1.9.183. any help or hint appreciated!

shaunlebron01:09:45

@jao: looks like a cljsbuild plugin error

jao01:09:48

shaunlebron, yes, that was my impression too. there's no direct reference to any of my code in the full stacktrace, so i'm having a hard time discovering a workaround

shaunlebron01:09:26

@jao: are you using cljsbuild 1.1.4?

jao01:09:29

@shaunlebron i had the same error with 1.1.3

shaunlebron01:09:20

@jao: I’d report an issue, but if you’re looking for a workaround, you can convert the project to a mies-like build to see if it works that way

jao01:09:58

@shaunlebron pardon my ignorance: a mies-like build?

shaunlebron01:09:40

it’s hard to know sometimes when errors are caused by build tools, since cljs changes pretty frequently

shaunlebron01:09:58

so the Quick Start tutorial uses direct build scripts

shaunlebron01:09:37

but that setup doesn’t establish a practical way to retrieve dependencies, so “mies” is a way to use lein with those build scripts to handle dependencies

shaunlebron01:09:59

it’s something I’m trying to fix with: https://github.com/cljs/tool

shaunlebron01:09:42

but you can use lein new mies to generate an example project with manual build scripts: https://github.com/swannodette/mies

jao01:09:26

i guess i'll give it a try

jao01:09:57

it'd be nice if i could produce a minimal test case, because right now this is happening with a biggish project i cannot share

jao01:09:17

thanks for your feedback!

shaunlebron01:09:37

@jao: if you DM me a cljsbuild project config, I can help you port it to one of the tools above if you want

shaunlebron03:09:06

for posterity, here’s @jao’s project config migrated off cljsbuild to use direct build scripts: https://github.com/shaunlebron/migrating-off-cljsbuild

Jon06:09:04

Since Elm posted a perf test, I added Respo here, Respo is totally in ClojureScript, and I got some questions, 1. Is ClojureScript essentially about 1.5 times slower comparing to native JavaScript? 2. why it looks a lot better when Timeline is running, compared to React, which is in native js?

juhoteperi07:09:13

@jiyinyiyong 1. It is not that simple. As this benchmark is for DOM libraries, I doubt language has much effect here, what this shows is that your DOM library is slower.

Jon07:09:30

yeah, the result is mixed of the library and the language runtime. Have you seen some tests on ClojureScript alone? I want to compare this result with that kind of things.

juhoteperi07:09:17

Hmm, I don't remember seeing language perf results. I remember seeing some React vs. Om vs. Reagent tests but don't remember where.

darwin07:09:41

@jiyinyiyong benchmarking is tricky, potential cljs slowdown compared to raw javascript can be caused by: 1) persistent data structures 2) the way how code is generated to achieve cljs semantics (wrapping code in immediately executed anonymous functions to introduce proper scoping for let, cljs truth checking, etc.) 3) DOM/browser APIs interaction In general I’m not afraid of cljs performance. I write code primarily in cljs. When I anticipate a performance-critical code I write it still in cljs but without persistent data structures using js interop. And lastly when encountering a performance issue, I use Chrome DevTools to analyze the problem and replace the hot code with a javascript implementation.

Jon10:09:25

Actually I want to make sure my code is faster enough since ClojureScript is probably slower than native js. I ran out of ideas to optimize it. And I will not rewrite it with js because I will want full power of the virtual DOM in immutable data.

xcthulhu13:09:26

> 1. Is ClojureScript essentially about 1.5 times slower comparing to native JavaScript? @jiyinyiyong This is a tough question. There's a lot of ways to sabotage JS performance in pure JS - for instance, if you are creating a lot of classes dynamically with overloaded operators, you'll see performance degradation because the JITs aren't designed for that thing. It's harder to write this sort of thing in ClojureScript because it simply doesn't expose that stuff to you. Moreover, there are many different JS engines - Google's V8, Firefox's SpiderMonkey, Apple's Nitro, Microsoft's Chakra and Java's Nashorn. YMMV depending on what engine you are using.

xcthulhu13:09:53

Now, I'm probably going to be booted from this channel for saying this, but honestly being puritanical about writing everything in ClojureScript is silly. In ClojureScript especially, it's really easy to write vanilla JS that calls clojurescript and vice versa. Here's an example of my own - https://github.com/Sepia-Officinalis/secp256k1/blob/master/src/js/secp256k1/sjcl/hash/Ripemd160.js

xcthulhu13:09:22

Writing a hashing function in ClojureScript would pointlessly slow it down

dnolen14:09:41

@xcthulhu not completely true, we implemented Murmur3 in ClojureScript for value hashing

dnolen14:09:54

it’s no slower than if we’d written it in JavaScript

dnolen14:09:42

it does require experience to understand what style of ClojureScript produces optimal JS

dnolen14:09:51

so it’s not an idiomatic thing to do most of the time

xcthulhu14:09:23

Yeah, you are right. I could rewrite RIPEMD-160 in cljs using a ton of set! assignments and it would compile to the same thing.

xcthulhu15:09:23

@jiyinyiyong Even though you can use JS side-by-side with CLJS just fine, it might not be a good idea, since I'm not sure this is officially supported and could break in a future release. Similarly, it's definitely not good practice to use (js* "...")

xcthulhu15:09:56

Maybe a core dev has a better idea than me.

nickt15:09:12

hey @dnolen you around? The other day you explained to me that the #js reader happens before macro compile time, and that clj->js happened at runtime, and a couple other similar details. So I have a macro that takes a #js form, and I can inspect and operate on the map wrapped in that JSValue by accessing (.-val jsval)... is there anyway to mutate that map within the JSValue? Or to create a new JSValue in it's place with the updated map? (at macro expand time)

dnolen15:09:36

there’s no way to mutate it no, but you can make a new JSValue

nickt15:09:03

@dnolen yesss thank you

nickt15:09:46

in that way you could take any map and convert it to a JSValue at macro time yea?

nickt15:09:56

effectively invoking #js at macro time instead of at reader time

dnolen15:09:21

well all #js does is construct a JSValue at read time

dnolen15:09:32

nothing is stopping you from using JSValue in your macro though directly

nickt15:09:41

right, that's what i mean

nickt15:09:55

so you could effectively insert #js tags at macro time

nickt15:09:02

(just by constructing JSValue's)

dnolen15:09:08

yes you could interpret it that way

dnolen15:09:16

but what I said above is how it works

nickt15:09:32

yep i got it

nickt15:09:35

that's awesome! thank you

nickt15:09:44

why do you have to (:require [cljs.tagged-literals :as tags]) but (:import [cljs.tagged_literals JSValue])

nickt15:09:53

(note the hyphen vs underline in tagged literals)

anmonteiro16:09:24

@nickt hyphens are not valid in Java names, so Clojure munges them to underscores

nickt16:09:07

@anmonteiro and import references java types?

anmonteiro16:09:29

import imports Java classes, yes

anmonteiro16:09:15

(`deftype` and defrecord generate Java classes)

hueyp16:09:01

reading above — is JSValue a placeholder for something, or like that is actual code I can use? 😜 (don’t see it here: http://cljs.github.io/api/)

dnolen16:09:08

@hueyp it’s somewhat of an internal detail, there’s no need to document it at all

hueyp16:09:45

is there an idiomatic way to create a js object at macro time?

hueyp16:09:53

it sounded like JSValue was?

dnolen16:09:07

nothing about idiomatic was ever said

dnolen16:09:24

if you use JSValue you should be OK with your code breaking at anytime

hueyp16:09:19

gotcha, thanks!

hueyp16:09:49

I had been using js-obj but never looked at when it happened 🙂

shaunlebron16:09:30

@hueyp: if you look at the sidebar of http://cljs.github.io/api/ you’ll see some namespaces under “Compiler"

shaunlebron16:09:59

I decided to only document the namespaces that are public, so the Compiler’s cljs.core is just left out, where JSValue would be

shaunlebron16:09:59

but it might be good to document those anyway since I’ve seen people here starting to use it for browsing the compiler in general

hueyp16:09:56

thanks, I didn’t mean it as a complaint, I just wasn’t sure if it was literally JSValue in code or a placeholder for like JSObject / JSArray / etc in the conversation 😜 … but thanks to the docs I just looked at the reader literal source code (so thanks)

shaunlebron16:09:14

didn’t take it as one, just thought it might be a good time to clarify something that could possibly change in the future. glad the reader literal source helped!

darwin16:09:54

any ideas how to work-around this? http://dev.clojure.org/jira/browse/CLJS-1631 have some code heavily using ES6 symbols and this makes cljs printing unusable for anything including symbols 😞

jdkealy17:09:32

Hi. I'm trying to use core.async in the browser to "avoid callback hell"... and I've seen people do the following gist more or less but without setting a buffer size. When I try to do the same, my code never gets past the first put and I need to manually set the buffer size to a value greater than 1. I'm trying to basically get the code to park after step 2 to wait for a value to be put on the channel from step 1. This works but I'm wondering if I'm doing something wrong by having to set the buffer size. https://gist.github.com/jdkealy/17b4e3649c646067f666aa4cff05e7f3

dnolen17:09:03

@darwin will look at that one eventually but until then you’ll just have to sort out some hack on your own

darwin17:09:10

I just read through the comments in other linked issues, and it looks that a performant solution will be hard to achieve 😞

darwin17:09:42

I can just monkey-patch cljs.core.str for now

dnolen17:09:22

yes it’s a super nasty corner of JavaScript all around

martinklepsch17:09:07

(:x (atom nil)) — why does this work? Is there a use case or is that more of a coincidence?

martinklepsch17:09:28

(note the lack of deref)

tanzoniteblack17:09:17

@martinklepsch it only works because keywords as a function only work on things that are associative, and return nil when they aren't

tanzoniteblack17:09:23

so (:x “cat”) will also return nil

tanzoniteblack17:09:38

and (:x (atom {:x "five"})) returns nil as well, since atoms don’t work with keywords

martinklepsch17:09:10

ugh, even strings... 😐

tanzoniteblack17:09:26

so rather than throwing an error to say that this type doesn’t work with keywords, it just returns nil, assuming that because the argument doesn’t support associative values, then the value associated with the keyword doesn’t exist, i.e. nil; which is terribly useful because this means we don’t have to make nil a special case for associativeness and still don’t have to check to see if if a map exists before passing it into the keyword

tanzoniteblack17:09:44

Numbers too! (:x 5) ==> nil

martinklepsch17:09:33

@tanzoniteblack thanks for the explanation

martinklepsch17:09:26

I'm not sure I understand why this is terribly useful though. When doing (:x nil) and that returns nil that seems handy, yes but in any other case I can think of there's likely a programming error

martinklepsch17:09:40

but I guess this is a very fundamental thing about typed vs. dynamic so I'll just accept it 🙂

shaunlebron17:09:37

@jdkealy: try using (.setTimeout js/window #(put! c “hello”) 10000) instead, looks like >! parks if there’s no buffer. I’ve never used >! though

darwin17:09:36

@martinklepsch I think you could override IFn on the Keyword deftype and make it behave your way - a great way how to confuse people reading your code 😉

martinklepsch17:09:15

Gonna put that into every library (I make) 😄

nickt18:09:17

do nested macros expand top down or bottom up?

nickt18:09:50

as in, (macro1 x y (macro2 z))

nickt18:09:54

which one expands first?

selfsame18:09:24

outer I believe

shaunlebron18:09:15

since macro arguments are not evaluated, I would assume outer-inner order

selfsame18:09:04

yeah, you can emit macro symbols in a macro

nickt18:09:39

cool thanks

shaunlebron18:09:48

or, just try this in planck to prove it:

cljs.user=> (macroexpand-1 '(+ 1 (+ 2 3)))
(js* "(~{} + ~{})" 1 (+ 2 3))

nickt18:09:14

what's planck?

smw18:09:32

pure awesome

shaunlebron18:09:36

oh, brew install planck, it’s just a really fast native cljs repl

shaunlebron18:09:50

as well as a way to use cljs scripts as shell scripts

nickt18:09:56

oh yeaaaa awesome

smw18:09:36

(Thank you so much for the port to linux!!!!)

smw18:09:29

I really want to write a config management system in cljs via planck now. Tired of yaml as a programming language.

selfsame18:09:34

woah did not know it was on linux now

mfikes18:09:59

@selfsame As you can see it is in Alpha. If you need to build for another distro instructions here: https://github.com/mfikes/planck/tree/master/planck-c

mfikes18:09:59

Also #planck if you’d like more details

tomc19:09:21

Using goog-define with integers appears to be broken - the cljs compiler calls .setDefineToIntegerLiteral on the closure CompilerOptions object instead of .setDefineToNumberLiteral. Does anyone know whether this has been reported?

nickt20:09:13

if I get an unqualified symbol blah how can I check whether or not it exists in a given namespace?

shaunlebron20:09:04

@tomc: search for goog-define at top right of http://dev.clojure.org/jira/browse/CLJS, I don’t see an issue related to your problem, so you may wanna report

tomc20:09:25

@shaunlebron thanks. I did the same thing but am wholly unfamiliar with jira so I assumed I'd done something wrong.

shaunlebron20:09:09

well, i don’t think anyone is wholly familiar with jira

dnolen20:09:13

@tomc pretty sure it’s never been reported

dnolen20:09:25

ticket + patch welcome, make sure you’ve sent in your CA - thanks!

tomc20:09:35

@dnolen thanks - I opened the issue and will make a patch for it asap

stbgz21:09:25

hey all not sure everyone saw this announcement

bostonaholic21:09:29

> we compile the Java source to JS to run under Node

shaunlebron22:09:16

The path to a full-JS cljs build tool is: 1. bootstrapped compiler 2. closure compiler in js 3. maven dependency retrieval in js

shaunlebron22:09:38

getting closer!

shaunlebron22:09:12

if anyone is interested in tackling it, we essentially need this in Node: https://github.com/cljs/dep-resolver

martinklepsch22:09:38

Is there something like Clojurescripts specify in Clojure?

martinklepsch22:09:46

E.g. I want to add a protocol implementation to a given value

anmonteiro22:09:53

@martinklepsch by “given value” do you mean instance?

ghadi22:09:36

Closure compiler in js was a huge surprise to me

anmonteiro22:09:52

right, so that’s not possible

anmonteiro22:09:13

it’s a limitation of Java that JavaScript doesn’t have

martinklepsch22:09:31

I essentially want to create a default atom with an extra Protocol implemented and no changes otherwise

martinklepsch22:09:31

But I wouldn't really want to modify the Atom type itself

anmonteiro22:09:03

you can use reify...

martinklepsch22:09:36

but then I need to add all the default atom protocols as well, no?

anmonteiro22:09:07

hrm, probably

martinklepsch22:09:33

Ideally I'd create some kind of proxy type that would default to Atom but extended by one protocol

stbgz22:09:14

@shaunlebron not sure exactly was is it that we need, do you mind expanding a little more

anmonteiro22:09:16

@martinklepsch couldn’t proxy do the job?

anmonteiro22:09:13

clojure.lang.Atom is a class after all

anmonteiro22:09:36

ah but it’s final 😞

martinklepsch22:09:44

@anmonteiro what does that mean? after looking at it I'm thinking it might work...

martinklepsch22:09:52

(defprotocol IDisposable
  (dispose! [this]))

(defn make-disposable-atom
  []
  (proxy [clojure.lang.Atom IDisposable] []
    (dispose! [] (prn 'disposing))))

anmonteiro22:09:12

java.lang.VerifyError: Cannot inherit from final class

anmonteiro22:09:16

this is what I got

anmonteiro22:09:45

also you’d have to definterface, not defprotocol

martinklepsch22:09:33

Well, I got to sleep but I'll get back to this tomorrow. Protocols seem to be much nicer/easier in CLJS than CLJ (interestingly)

anmonteiro22:09:58

@martinklepsch I don’t think you can blatantly say “nicer"

anmonteiro22:09:10

it’s just that JavaScript allows you to patch an Object at runtime 🙂

anmonteiro22:09:26

you can’t add methods to a Java instance, that I know of

martinklepsch22:09:07

well yes, it comes at other costs. It just seems more consistent in CLJS, probably only made possible by being dangerous elsewhere 🙂

martinklepsch22:09:15

Thanks for your suggestions Antonio. I'll see what I end up with 🙂 👋