Fork me on GitHub
#clojurescript
<
2021-03-22
>
Eugene15:03:09

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.”

dpsutton15:03:00

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

Eugene15:03:23

This is the deps.edn in the project directory:

Eugene15:03:30

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

dpsutton15:03:38

{: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

dpsutton15:03:11

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

Eugene15:03:28

Awesome! Thank you @dpsutton That was the problem!

Ronny Li17:03:44

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

leif17:03:49

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?

jaide20:03:38

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.

localshred20:03:31

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

localshred20:03:05

(sql "SELECT * FROM my-table")

localshred21:03:40

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

localshred21:03:40

the 0th argument to the fn is the template string

localshred21:03:01

the n+ args are the interpolated values

jaide21:03:38

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]}

jaide21:03:10

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

leif20:03:54

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

leif21:03:06

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.

leif21:03:28

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

leif21:03:36

Is that correct behavior?

leif21:03:40

(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?

leif21:03:41

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

mkvlr21:03:35

@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.

leif21:03:30

@mkvlr Thanks for pointing those out.

leif21:03:52

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

leif21:03:07

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

leif21:03:12

But maybe I'm wrong?

blak3mill3r21:03:59

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

leif21:03:38

Rats. oh well

leif21:03:05

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

leif21:03:42

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

blak3mill3r21:03:16

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)

blak3mill3r21:03:12

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

leif21:03:50

@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.

leif21:03:55

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

borkdude21:03:36

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

borkdude21:03:24

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

😹 6
leif21:03:00

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

borkdude21:03:40

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

leif21:03:50

@borkdude That's not a bad idea actually.

borkdude21:03:58

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

leif21:03:18

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. 😉

mkvlr21:03:31

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

borkdude21:03:12

those were experimental and were never implemented

borkdude21:03:26

after I saw that it wasn't good enough

borkdude21:03:05

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

borkdude21:03:10

but that was removed as well

phronmophobic21:03:21

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

leif21:03:08

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

leif21:03:36

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

blak3mill3r21:03:46

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

leif22:03:01

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

leif22:03:04

Thanks for the suggestion.

blak3mill3r22:03:23

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

blak3mill3r22:03:34

kinda like core.async...

borkdude22:03:09

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

leif22:03:12

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

blak3mill3r22:03:32

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

borkdude22:03:34

luckily JS doesn't have Thread/sleep

leif22:03:19

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

borkdude22:03:47

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 ;)

blak3mill3r22:03:02

Yeah I thought for a moment about WebWorkers

blak3mill3r22:03:20

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

leif22:03:25

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

leif22:03:46

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

leif22:03:54

(Ideally directly.)

blak3mill3r22:03:16

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

leif22:03:35

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

leif22:03:49

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

leif22:03:15

Modified from a recent message I sent to Arjun:

<script src=""></script>
<script>
const prog = `
var i = 0;
debugger;
while(i < 10) {
    console.log(i);
    i = i + 1
};`;
let runner = stopify.stopifyLocally(prog);
runner.g = {console};
runner.run(() => {
    console.log(runner.g.i);
    console.log("DONE!");
});
</script>

borkdude22:03:25

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

borkdude22:03:52

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

leif22:03:56

oh, good idea.

borkdude22:03:30

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

borkdude22:03:58

and usually you want to include a lib or so anyway

leif22:03:13

LOL

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

leif22:03:42

Probably a different package.

leif22:03:03

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

borkdude22:03:07

Yeah, still seems to work:

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

leif22:03:05

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

leif22:03:26

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, …}

leif22:03:52

Code is:

leif22:03:54

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(() => {console.log("DONE!");});

borkdude22:03:27

@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

borkdude22:03:52

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

leif22:03:26

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

borkdude22:03:00

try (doall (range))

borkdude22:03:20

@leif

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

leif22:03:53

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

borkdude22:03:25

does stopifyLocally only accept JS code as strings as input?

leif22:03:25

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

leif22:03:47

No, it can also accept babel AST nodes.

leif22:03:27

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.

borkdude22:03:38

it isn't doing that

borkdude22:03:08

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

leif22:03:52

Ah, okay, never mind then.

leif22:03:07

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

leif22:03:19

This is what I needed to do.

leif22:03:32

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(() => {console.log("DONE!");});

leif22:03:55

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

blak3mill3r22:03:30

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

borkdude22:03:26

what is runner.g?

leif22:03:36

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

leif22:03:43

(from the outside world)

leif22:03:11

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.

leif22:03:24

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! 🙂