clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
grounded_sage 2021-03-22T14:10:50.166500Z

I’m assuming that this also applies to Cljs libraries.. https://blog.fikesfarm.com/posts/2017-11-18-clojurescript-performance-measurement.html cc @mfikes

Eugene 2021-03-22T15:19:09.167500Z

I’m working through @asmeredith’s Learn Clojurescript. Is listing 5.4 is the same deps.edn file as listing 5.1? I added the aliases, ran clj -M:dev, and got “Error building classpath. Error reading edn. Invalid file, expected edn to contain a single value.”

dpsutton 2021-03-22T15:24:00.167800Z

can you post the contents of the deps.edn file here?

Eugene 2021-03-22T15:43:23.168400Z

This is the deps.edn in the project directory:

Eugene 2021-03-22T15:43:30.168600Z

{:deps {org.clojure/clojurescript {:mvn/version “1.10.773”}} :paths[“src”]} :aliases {:dev {:main-opts [“-m” “cljs.main” “--compile” “test-cljs-project.core” “--repl”]}}

dpsutton 2021-03-22T15:47:38.169400Z

{:deps {org.clojure/clojurescript {:mvn/version “1.10.773”}}
 :paths[“src”]
 :aliases
 {:dev {:main-opts [“-m” “cljs.main”
                    “--compile” “test-cljs-project.core”
                    “--repl”]}}}
you had aliases and the map it corresponded to outside of the top level map

dpsutton 2021-03-22T15:50:11.170Z

which is why the tooling was complaining that the edn file had more than one value. It should have only a single map

Eugene 2021-03-22T15:51:28.170500Z

Awesome! Thank you @dpsutton That was the problem!

Ronny Li 2021-03-22T17:09:44.171900Z

Hi 👋 Has anyone tried out the re-dnd library? How does it compare to say react-dnd?

2021-03-22T17:15:49.172900Z

The function compile-str in cljs.js doesn't seem to ever call the finished callback, I'm not sure what's going on, any suggestions on the best way to debug this?

2021-03-22T20:40:38.175Z

Is there a way to use template literal tag functions from js in cljs? I need to do

sql`SELECT * FROM my-table
` but not sure how, or if it’s possible.

localshred 2021-03-22T20:57:31.175400Z

If I'm not mistaken tagged template literals are still just functions, so you should be able to call the fn with the string as the only argument

localshred 2021-03-22T20:58:05.175600Z

(sql "SELECT * FROM my-table")

2021-03-22T20:58:54.176500Z

Okay, I did finally get the compile function to return. Although now I have another question:

2021-03-22T21:00:06.177900Z

When I use eval-str in cljs.js on some module B that requires module A, the load function finds the module A, and then executes both module A and B.

2021-03-22T21:00:28.178400Z

However, if I use compile-str instead, the load function seems to find both A and B, but only seems to compile B.

2021-03-22T21:00:36.178600Z

Is that correct behavior?

localshred 2021-03-22T21:00:40.178800Z

ah, I've misunderstood slightly. the template literal fn only receives args for the interpolated values positionally, not the whole string as it's only arg

2021-03-22T21:01:40.180400Z

(And if so, is there any way I can get a compile-str like function, that either: (i) compiles A and B together, or (ii) compiles B in a way that doesn't require me to manually call compile-str on A?

localshred 2021-03-22T21:01:40.180500Z

the 0th argument to the fn is the template string

localshred 2021-03-22T21:02:01.180700Z

the n+ args are the interpolated values

localshred 2021-03-22T21:02:11.180900Z

2021-03-22T21:07:41.181700Z

(When I do try to pass the result of compile-str to js/eval I get: Error: goog.require could not find: A.core)

mkvlr 2021-03-22T21:19:35.185900Z

@leif https://clojure.atlassian.net/browse/CLJS-3288 and https://clojure.atlassian.net/browse/CLJS-3286 are two open issues regarding self-hosted cljs to be aware of. We recently switched to https://github.com/borkdude/sci for eval and are quite happy with it, found it less complex to setup and it’s lighter weight. It even works with advanced compilation. The downside is that it’s a slower as it’s an interpreter, not a compiler.

2021-03-22T21:25:30.186400Z

@mkvlr Thanks for pointing those out.

2021-03-22T21:25:52.186900Z

I'm looking for something that can output javascript that I can potentially transform with babel, can sci do that?

2021-03-22T21:26:07.187200Z

It 'looks' like its mostly an evaluator to me.

2021-03-22T21:26:12.187400Z

But maybe I'm wrong?

blak3mill3r 2021-03-22T21:32:59.187700Z

You're correct that sci is a clojure interpreter (not a compiler)

2021-03-22T21:35:38.187900Z

Thanks! I also tried the template tag in node and realized it just returns

{sql: "SELECT * FROM tabl WHERE id=$1",
 type: "SLONIK_TOKEN_SQL",
 values: [7]}

2021-03-22T21:35:38.188100Z

Rats. oh well

2021-03-22T21:36:05.188700Z

Although I guess if it has the capability to pause computations that would be enough for me.

2021-03-22T21:36:10.188900Z

But might do your suggestion so it at least looks like I’m trying to be a good user

2021-03-22T21:36:42.189800Z

(Like if I could set up (loop [] (recur)) to be breakable and not inherently freeze the browser until the tab is reloaded.

blak3mill3r 2021-03-22T21:39:16.190900Z

That sounds challenging (in a javascript environment) but not strictly impossible... I think you'd have to hack something into sci to allow evaluation to be interruptable with core.async (for example)

blak3mill3r 2021-03-22T21:40:12.191900Z

I don't know enough about sci but I'd say if you're willing to modify it, you should be able to make a core.async loop that does a few steps of evaluation and then checks if the kill channel has been closed

2021-03-22T21:45:50.193300Z

@blak3mill3r Oh, I'm using stopify (https://www.stopify.org/) right now, which seems to work surprisingly well for how small a project it is.

2021-03-22T21:46:55.193700Z

That's actually why I was using compile-str .

borkdude 2021-03-22T21:48:36.194100Z

@leif Maybe you can run sci (compiled as JS) itself through stopify? ;)

borkdude 2021-03-22T21:50:24.194500Z

FWIW I haven't been able to find a satisfying answer to the halting problem

😹 2
borkdude 2021-03-22T21:51:40.195300Z

Even when instrumenting sci with all kinds of checks, there is still probably a program that can work around it

2021-03-22T21:52:50.196400Z

@borkdude That's not a bad idea actually.

borkdude 2021-03-22T21:52:58.196900Z

There are advanced type systems with less powerful programming languages, like Dhall, which provably terminate

mkvlr 2021-03-22T21:53:00.197100Z

some inspiration to keep trying: https://m.youtube.com/watch?v=MdmQUlD7P40

2021-03-22T21:53:18.197800Z

Although ya, it would be nice if we could solve the halting problem, fortunately what I"m trying to do is MUCH simpler then that. 😉

mkvlr 2021-03-22T21:54:31.198700Z

but sci did have some flags to control execution time https://github.com/borkdude/sci/issues/348

2021-03-22T21:55:00.199300Z

I mean, the thing about CP(>0) is the answer is: "no, your analysis won't halt. 😉 )

borkdude 2021-03-22T21:55:12.199500Z

those were experimental and were never implemented

borkdude 2021-03-22T21:55:26.199700Z

after I saw that it wasn't good enough

mkvlr 2021-03-22T21:56:31.200300Z

but 0.1 still had them? https://github.com/borkdude/sci/blob/master/CHANGELOG.md#breaking-changes

borkdude 2021-03-22T21:57:05.200900Z

There were flags to control the max length of realization of lazy seqs

borkdude 2021-03-22T21:57:10.201100Z

but that was removed as well

mkvlr 2021-03-22T21:57:14.201400Z

ah right

phronmophobic 2021-03-22T21:58:21.202300Z

The https://arxiv.org/abs/1802.02974 seems to indicate that the techniques are more general than just javascript > We apply Stopify to 10 programming languages

2021-03-22T21:58:50.202600Z

@smith.adriane Only partially.

2021-03-22T21:59:08.203100Z

It applies to other languages if and only if they can compile to javascript.

phronmophobic 2021-03-22T21:59:23.203900Z

ah

2021-03-22T21:59:36.204700Z

When you look at the source code for their little clojurescript debugger demo, it actually compiles to javascript first.

blak3mill3r 2021-03-22T21:59:46.205100Z

Stopify sounds cool. I think you might have luck running sci with Stopify.

2021-03-22T22:00:01.205700Z

@blak3mill3r I'll give it a shot and let you know how it goes. 🙂

2021-03-22T22:00:04.206Z

Thanks for the suggestion.

blak3mill3r 2021-03-22T22:00:23.206400Z

I'm curious... I mean I guess Stopify must be doing some sophisticated static analysis and source->source translation

blak3mill3r 2021-03-22T22:00:34.206600Z

kinda like core.async...

borkdude 2021-03-22T22:01:09.207300Z

I think you can even fool core.async, by putting`(Thread/sleep 1000000)`, it won't help you there

2021-03-22T22:01:12.207400Z

I doubt its exactly like core.async, but same idea.

blak3mill3r 2021-03-22T22:01:32.208300Z

I mean that core.async's implementation details involve code splitting/rewriting using clojure macros

borkdude 2021-03-22T22:01:34.208500Z

luckily JS doesn't have Thread/sleep

2021-03-22T22:02:19.209700Z

@borkdude well that would be a recipe for freezes. 😉

borkdude 2021-03-22T22:02:47.210200Z

On the other hand, if it did, you could run your eval in a thread and then kill the thread if it took too long ;)

blak3mill3r 2021-03-22T22:03:02.210500Z

Yeah I thought for a moment about WebWorkers

blak3mill3r 2021-03-22T22:03:20.211300Z

run self-hosted cljs or sci in a WebWorker and perhaps there's an API to kill it after a timeout

2021-03-22T22:03:25.211500Z

@borkdude True, but aren't webworks a relatively recent addition to JS?

2021-03-22T22:03:46.211900Z

@blak3mill3r A webworker won't work, I want to manipulate the dom.

2021-03-22T22:03:54.212200Z

(Ideally directly.)

blak3mill3r 2021-03-22T22:03:59.212400Z

yeah

blak3mill3r 2021-03-22T22:04:16.213Z

you'd have to do that indirectly which would be a pain

2021-03-22T22:04:35.213400Z

Although I guess if its possible to get react working with actors (sounds painful), I'd be willing to give it a go.

2021-03-22T22:05:49.214Z

Oh, also, you can look at the compiled stopify output if you find that interesting.

2021-03-22T22:07:15.215Z

Modified from a recent message I sent to Arjun:

&lt;script src="<https://github.com/ocelot-ide/Stopify/releases/download/0.7.3/stopify-full.bundle.js>"&gt;&lt;/script&gt;
&lt;script&gt;
const prog = `
var i = 0;
debugger;
while(i &lt; 10) {
    console.log(i);
    i = i + 1
};`;
let runner = stopify.stopifyLocally(prog);
runner.g = {console};
runner.run(() =&gt; {
    console.log(runner.g.i);
    console.log("DONE!");
});
&lt;/script&gt;

borkdude 2021-03-22T22:08:25.215500Z

@leif there is (an old) version of sci on npm available, if you want to try it out quickly

borkdude 2021-03-22T22:08:52.216100Z

I guess you could try stopify.stopifyLocally(sci.evalString)

2021-03-22T22:08:56.216300Z

oh, good idea.

borkdude 2021-03-22T22:10:30.217100Z

I have deprecated the npm package more or less since it's way easier to configure it from CLJS and the compile it to JS yourself

borkdude 2021-03-22T22:10:58.217400Z

and usually you want to include a lib or so anyway

2021-03-22T22:11:13.217600Z

LOL

$ ls node_modules/sci
LICENSE  package.json  README.md

2021-03-22T22:11:42.218Z

Probably a different package.

2021-03-22T22:12:03.218200Z

"Yet another math library for your browser" yup. woops

2021-03-22T22:12:47.218400Z

Ah, found it: https://www.npmjs.com/package/@borkdude/sci

borkdude 2021-03-22T22:15:07.218800Z

Yeah, still seems to work:

&gt; const { evalString } = require('@borkdude/sci');
undefined
&gt; evalString("(str (assoc {:a 1} :b 2))")
'{:a 1, :b 2}'

2021-03-22T22:17:05.219300Z

Sadly it doesn't quite seem to work with stopify...although maybe I'm doing something wrong

2021-03-22T22:17:26.220Z

sci.js?3eac:910 Uncaught Mn {message: "Dc(...).append is not a function [at line 1, column 1]", data: k, Bc: TypeError: Dc(...).append is not a function
    at Function.VU.f (webpack-internal:///./node_module…, name: "Error", description: undefined, …}

2021-03-22T22:17:52.220600Z

Code is:

2021-03-22T22:17:54.220900Z

var stopify = require ('@stopify/stopify');
var sci = require('@borkdude/sci');
window.stopify = stopify;

let runner = stopify.stopifyLocally(sci.evalString("(println (+ 1 2))"));
runner.g = {console};
runner.run(() =&gt; {console.log("DONE!");});

borkdude 2021-03-22T22:18:27.221600Z

@leif this is a warning you will get when using println, this doesn't work with sci out of the box, you will have to bind the out stream to something

borkdude 2021-03-22T22:18:52.222300Z

so for just testing this, it's better to configure your own println or just avoid printing for now

2021-03-22T22:19:13.222500Z

oooh

2021-03-22T22:19:26.222800Z

So it 'might' actually be working...nifty.

borkdude 2021-03-22T22:20:00.223200Z

try (doall (range))

borkdude 2021-03-22T22:21:20.223400Z

@leif

&gt; evalString("(println (str (assoc {:a 1} :b 2)))", {"namespaces": {"clojure.core": {"println": console.log}}})
{:a 1, :b 2}

2021-03-22T22:21:53.223700Z

Hmm:

Uncaught TypeError: this.input.charCodeAt is not a function
    at Parser.fullCharCodeAtPos (index.js?0cd6:781)
    at Parser.nextToken (index.js?0cd6:766)
    at Parser.parse (index.js?0cd6:1672)
    at Object.parse (index.js?0cd6:7305)
    at Object.stopifyLocally (compiler.js?e91e:100)
    at eval (in.js?73b4:10)
    at Object../in.js (out.js:96)
    at __webpack_require__ (out.js:20)
    at out.js:84
    at out.js:87

borkdude 2021-03-22T22:22:25.224200Z

does stopifyLocally only accept JS code as strings as input?

2021-03-22T22:22:25.224300Z

Oh wait, I think I know what's going on.

2021-03-22T22:22:47.224600Z

No, it can also accept babel AST nodes.

2021-03-22T22:23:27.225800Z

But it just occurred to me that it could be that sci is putting something in the window object that the stopify sandbox isn't allowing.

borkdude 2021-03-22T22:23:38.226Z

it isn't doing that

borkdude 2021-03-22T22:24:08.226600Z

all mutation is local to sci, it never mutates the outside world unless you configure it to (hence no printing by default)

2021-03-22T22:24:52.226900Z

Ah, okay, never mind then.

2021-03-22T22:25:07.227300Z

Oh...right, I wasn't calling it right.

2021-03-22T22:25:19.227600Z

This is what I needed to do.

2021-03-22T22:25:32.228Z

var stopify = require ('@stopify/stopify');
var sci = require('@borkdude/sci');
window.stopify = stopify;

//console.log(sci.evalString("(+ 1 2"));
const prog = `
console.log(sci.evalString("(doall (range))"));
`;

let runner = stopify.stopifyLocally(prog);
runner.g = {console, sci};
runner.run(() =&gt; {console.log("DONE!");});

2021-03-22T22:25:55.228500Z

Sadly I suspect the runner.g = {...}; line at the bottom will break the sandbox. 😕

blak3mill3r 2021-03-22T22:26:30.228900Z

it's stoppable ^ like that? That's pretty nifty

2021-03-22T22:27:04.229100Z

@blak3mill3r Sadly no. 😞

borkdude 2021-03-22T22:27:26.229300Z

what is runner.g?

2021-03-22T22:28:36.229800Z

It tells stopify what objects can be in the sandboxed namespace.

2021-03-22T22:28:43.230100Z

(from the outside world)

2021-03-22T22:29:11.230800Z

So in this case, sci is coming in from the outside world. Hence why I suspect it doesn't work. So now I need to see if I can bring sci itself in.

2021-03-22T22:41:24.232400Z

Ah, sad. So I can't seem to get stopify to work with webpack packages just at the moment. I'll poke Arjun and see what he has to say. I'll get back to you about this later @blak3mill3r and @borkdude . Thanks for all your help btw! 🙂