Fork me on GitHub
#clojurescript
<
2019-08-05
>
mfikes01:08:05

Sounds fine to me. Another term I’ve used for js and Math is pseudo-namespace.

mfikes01:08:13

(I’ve seen the term synthetic used for the arbitrary namespaces bestowed to foreign libs.)

😊 4
scknkkrer08:08:37

Thank you. This PR explains a lot! 😇

mfikes01:08:56

Perhaps another good variant might be intrinsic namespace, given the special handling given to them by the compiler.

4
jakuzure06:08:22

I'm trying to add a js dependency (https://github.com/lipis/flag-icon-css), I installed it via yarn and required it like this ["flag-icons-css" :as flag], but I'm getting an error "module without entry or suffix flag-icons-css"

jakuzure06:08:30

maybe the problem is that it's a css thingie? is it possible to include it then?

thheller07:08:44

@shin no, they cannot be included as part of a CLJS build. need to use some other tools to build CSS (eg. node-sass)

jakuzure07:08:22

@thheller hmm, seems complicated, I was just looking for a quick way to include country flags

thheller07:08:58

including it manually is quick and easy (with no extra tools)

jakuzure07:08:37

could you tell me how to do that?

Aklscc09:08:30

I'm trying to translate javascript code to clojurescript, which with a property value of the Object is a anonymous function. What should I do? For example:

var Navigator = {
    options: ({tintColor, focused}) => {
        <Bar 
          tintColor={tintColor}
          focused={focused}
        />
    }
}
The code used a library "react navigation", and the parameters tintColor and focused is immutable in thier name.

thheller09:08:58

@180338742 JS objects cannot be destructured like this so you'd do (fn [^js obj] (use (.-tintColor obj) (.-focused obj)) or use libs like https://github.com/appliedsciencestudio/js-interop https://github.com/mfikes/cljs-bean

👍 4
Aklscc09:08:36

Thank you very much, I will try it.

Aklscc11:08:14

Hello, everyone! Can any one explain the ^js meaning or giving me some links to learn it?

thheller11:08:01

^js is a typehint telling the compiler that the object is a JS object and instructing the compiler to generate externs and prevents the renaming in :advanced builds. see https://clojurescript.org/guides/externs#externs-inference

romdoq13:08:30

Has anyone else noticed an unusual amount of "aw snap"s when developing using chrome/chromium 76? Perhaps particularly under (Debian) Linux? I'm working on a re-frame cljs portion of a rather large js web app, and I was hitting "aw snaps" a lot this morning after upgrading chromium (73->76) on Friday. It's not been the only trigger, but the shadow-cljs hot-reloading seemed to cause "aw snap" moments quite often. I've had to downgrade back to version 73 to get any work done. 😕

thheller13:08:01

@mel.collins some people have reported crashes like that in projects with an excessive amount of files (thousands ...). this seems to help to address that https://clojureverse.org/t/improving-initial-load-time-for-browser-builds-during-development/2518

thheller13:08:22

although nobody reported this as happening during hot-reload? only initial load

romdoq13:08:11

@thheller To throw in another curveball, is that also applicable to :target :npm-module projects?

thheller13:08:37

no. it is not since it doesn't apply for those

thheller13:08:08

but if you process the code further via say webpack that already does pretty much the same

romdoq13:08:01

hm, yeah webpack is indeed in use

thheller13:08:18

yeah that already packages the sources so it doesn't matter

romdoq14:08:16

Welp, apparently it hits some kind of "illegal instruction" within Chromium's v8 JS compiler. Reproduction is a real pain though - could happen on first load, could only occur after 30 minutes of interactions and hot-reloading. 😕

henrik14:08:46

Has anyone else run into this difference between clj and cljs?

;; CLJ
(re-seq #"^[a-f]" "aabcded") ;; => ("a")

;; CLJS
(re-seq #"^[a-f]" "aabcded") ;; => ("a" "a" "b" "c" "d" "e" "d")

henrik14:08:32

Is it a difference in regex syntax or in the function proper?

dominicm14:08:18

the cljs solution is recursive, which means it ends up running #"^[a-f]" against e.g. "ded" which matches. Seems like a cljs bug to me.

henrik14:08:26

Ah, shite. That screws things up.

henrik14:08:40

I’ll go and post on the new forum, then.

henrik14:08:12

Actually, check I’ll Jira if it isn’t in there already.

scknkkrer14:08:57

@U06B8J0AJ, @U04VDQDDY; I think it shouldn’t be like that.

thheller14:08:59

always remember that regexes are host specific. so it might just be how JS handles regexes differently than the JVM

dominicm14:08:38

No, this is not that.

dominicm14:08:55

clojurescript is not correctly checking the lastIndex property of the regex before deciding whether to recurse or not. If it is zero then it should not recurse, as there's no more matches.

dominicm14:08:19

I would answer, and provide a working re-seq implementation, but I'm not sure whether that should be left for someone else to open a jira to match it in? I guess I can try and let the downvotes decide.

👍 4
henrik14:08:55

I don’t see how it could hurt.

Roman Liutikov14:08:17

I think there’s jira for that, but it’s on hold since might break existing users

👍 4
dominicm15:08:15

ah, using lastIndex is problematic because of the regex mutability and laziness.

henrik15:08:31

As per Rich’s recommendations, the solution is to make a re-seq-2 😉

😅 8
dominicm15:08:46

if you tried to do something like:

(let [re #"."]
  [(take 1 (re-seq re "foo")) (take 1 (re-seq re "bar"))])
You would get unexpected results perhaps, will test 😄

henrik15:08:49

It’s not listed among ClojureScript differences: https://www.clojurescript.org/about/differences, is this due to its bug status?

henrik15:08:42

(Does keeping it on hold make any sense? Either it’s never going to break anything, or it’s forever going to break something.)

Roman Liutikov15:08:39

I’m not sure if there’s jira for this particular problem tbh, just seen something related the other day

8
dominicm15:08:43

Actually, a great workaround is making the regex sticky @U06B8J0AJ, this should definitely be what re-seq should do.

👍 8
henrik15:08:39

Yep, that does it:

(re-seq (js/RegExp "^[a-f]" "y") "aabcded") ;; => ("a")

henrik15:08:47

@U09LZR36F Do you want to chuck that fact into the thread over at ask for posterity?

henrik15:08:36

Way ahead of me, I see.

dominicm15:08:37

I have 🙂 there's a caveat with doing it that way unfortunately.

dominicm15:08:48

just that you have to remember to clone every time you call re-seq else you'll get issues with state

henrik15:08:00

Sticky doesn’t seem to make it quite equivalent to the CLJ version, upon testing:

;; CLJ
(re-seq #"[a-f]" "aabcded") ;; => ("a" "a" "b" "c" "d" "e" "d")

;; CLJS (sticky)
(re-seq (js/RegExp. #"[a-f]" "y") "aabcded") ;; => ("a" "b" "e")

;; CLJS (re-seq2)
(re-seq2 #"[a-f]" "aabcded") ;; => ("a" "b" "d" "d")

henrik15:08:25

(This is now without caret)

Gabriel15:08:54

Hello. I'm a node.js/python dev messing around with ClojureScript. I came here because I noticed that using --optimizations advanced deteriorates performance! The Clojure code I'm using:

(ns hello-world.core)

(defn fibo [n]
  (case n
    0 0
    1 0
    2 1
    (+ (fibo (- n 1)) (fibo (- n 2)))))

(defn -main [& args]
  (fibo (int (first args))))

(set! *main-cli-fn* -main)
I'm compiling with
clj -m cljs.main --target node --optimizations advanced --output-to main.js -c hello-world.core
And using the free unix executable to measure execution time:
time node main.js 40
When I use --optimizations none the execution time is 4x smaller.

bfay15:08:07

From what I understand, the purpose of the clojurescript optimizations is more to reduce the size of the compiled javascript (not so much to improve performance). It's probably not particularly useful to turn on optimizations when you're running clojurescript on node; your code isn't going over the wire so why bother?

lilactown15:08:28

I think shadow-cljs defaults to simple optimizations

lilactown15:08:45

for node scripts

Gabriel15:08:58

@bfay I see. It makes sense now.

lilactown15:08:11

I based that assumption off of this verbiage in the user guide: https://shadow-cljs.github.io/docs/UsersGuide.html#target-node

thheller15:08:32

hmm yeah that is out of date

thheller15:08:06

removed. thanks.

👍 4
Jimmy Miller17:08:46

@gabrielblanksm I can't say why the clojurescript compiler is doing this. But is turning your code into this in advanced compilation (before minification).

hello_world.core.fibo = function hello_world$core$fibo(n) {
  var G__526 = n;
  switch (G__526) {
    case 0:
      return 0;

      break;
    case 1:
      return 0;

      break;
    case 2:
      return 1;

      break;
    default:
      return (
        (function() {
          var G__527 = n - 1;
          return hello_world.core.fibo.cljs$core$IFn$_invoke$arity$1
            ? hello_world.core.fibo.cljs$core$IFn$_invoke$arity$1(G__527)
            : hello_world.core.fibo(G__527);
        })() +
        (function() {
          var G__528 = n - 2;
          return hello_world.core.fibo.cljs$core$IFn$_invoke$arity$1
            ? hello_world.core.fibo.cljs$core$IFn$_invoke$arity$1(G__528)
            : hello_world.core.fibo(G__528);
        })()
      );
  }
};

The extra function definitions and calls account for the slow down. It seems like to me this shouldn't happen because :static-fns should optimize this. Not sure why it produces such suboptimal code.

alexeiz17:08:31

anybody has a good example of how to setup emacs/cider/shadow-cljs properly? I'm not able to get repl working in emacs

dpsutton17:08:40

it works straight forward to me. come chat in #cider ? and we can diagnose?

Gabriel17:08:05

@jimmy and @bfay I ran some more tests, here are the results:

optimization level,command arg,execution time (ms)
none,1,690
none,40,2100
simple,1,550
simple,40,2050
advanced,1,470
advanced,40,8600

alexeiz17:08:51

@dpsutton - thanks, I posted my problem in #cider

dnolen19:08:09

@gabrielblanksm yes this is known - but not really all that interesting in practice - code size generally more important than absolute throughput

dnolen19:08:01

but also as I'm sure you're aware - performance is a really complicated - and such small tests in isolation generally do more to obscure then provide any light

Gabriel21:08:22

@dnolen Just to summarize the difference between advanced and none: A reduction of 13% in the code size and a 300% slowdown in execution time. You're totally right tho; profiling such a small script is not a good way to predict the behavior of a real world application. Also, this is the first time I program in clojurescript, so I'm not in a position to criticize anything, I still need to learn a lot.

thheller21:08:54

@lewis FWIW I just run this on my machine and got practically no difference. advanced version is a tiny bit faster given that there is less code to load

Gabriel21:08:46

@thheller With 40 as the command line argument?

Gabriel21:08:05

what you described is what I see with 1 as argument, the advanced is ~30% faster because there's less code to load

Gabriel21:08:36

what is your node --version?

thheller21:08:38

$ time node script.js 40
63245986

real    0m2.003s
user    0m1.766s
sys     0m0.406s

thheller21:08:32

(added a prn to print the result to verify, assuming thats correct :)

thheller21:08:50

node v10.13.0

Gabriel21:08:27

hum my node even older, I'll upgrade it asap and check again

mfikes21:08:49

@gabrielblanksm If you're curious about :advanced across different engines, the test suite in the compiler might also be of interest. See https://blog.fikesfarm.com/posts/2017-11-18-clojurescript-performance-measurement.html

dnolen22:08:29

Measuring code size reduction for such trivial programs isn’t something we care that much about since there’s no benefit for the actual use case

dnolen22:08:36

Runtime perf is really important but we don’t test naive fib :) mostly interested in functional patterns and persistent data structures